Changes for IoThink test cases
ADD
test/api/AssetIntegrationTest.ts
+import chai, { expect } from 'chai';
+
+import Asset from '../../src/types/Asset';
+import CentralServerService from './client/CentralServerService';
+import Company from '../../src/types/Company';
+import ContextDefinition from './context/ContextDefinition';
+import ContextProvider from './context/ContextProvider';
+import Factory from '../factories/Factory';
+import { Setting } from '../../src/types/Setting';
+import Site from '../../src/types/Site';
+import SiteArea from '../../src/types/SiteArea';
+import TenantContext from './context/TenantContext';
+import chaiSubset from 'chai-subset';
+
+chai.use(chaiSubset);
+
+class TestData {
+ public centralUserContext: any;
+ public centralUserService: CentralServerService;
+ public userContext: any;
+ public tenantContext: TenantContext;
+ public userService: CentralServerService;
+ public newCompany: Company;
+ public newSite: Site;
+ public newSiteArea: SiteArea;
+ public newAsset: Asset;
+ public newAssetConnector: Setting;
+ public createdCompanies: Company[] = [];
+ public createdSites: Site[] = [];
+ public createdSiteAreas: SiteArea[] = [];
+ public createdAssets: Asset[] = [];
+}
+
+const testData: TestData = new TestData();
+
+describe('AssetIntegration', function() {
+ this.timeout(1000000); // Will automatically stop the unit test after that period of time
+
+ before(async () => {
+ chai.config.includeStack = true;
+ await ContextProvider.defaultInstance.prepareContexts();
+ });
+
+ afterEach(() => {
+ // Can be called after each UT to clean up created data
+ });
+
+ after(async () => {
+ // Final clean up at the end
+ await ContextProvider.defaultInstance.cleanUpCreatedContent();
+ });
+
+ describe('Where admin user', () => {
+
+ before(async () => {
+ testData.userContext = testData.tenantContext.getUserContext(ContextDefinition.USER_CONTEXTS.DEFAULT_ADMIN);
+ if (testData.userContext === testData.centralUserContext) {
+ // Reuse the central user service (to avoid double login)
+ testData.userService = testData.centralUserService;
+ } else {
+ testData.userService = new CentralServerService(
+ testData.tenantContext.getTenant().subdomain,
+ testData.userContext
+ );
+ }
+ // Create a new Company
+ testData.newCompany = await testData.userService.createEntity(
+ testData.userService.companyApi,
+ Factory.company.build()
+ );
+ testData.createdCompanies.push(testData.newCompany);
+ expect(testData.newCompany).to.not.be.null;
+ // Create a new Site
+ testData.newSite = await testData.userService.createEntity(
+ testData.userService.siteApi,
+ Factory.site.build({
+ companyID: testData.newCompany.id
+ })
+ );
+ testData.createdSites.push(testData.newSite);
+ expect(testData.newSite).to.not.be.null;
+ // Create a new Site Area
+ testData.newSiteArea = await testData.userService.createEntity(
+ testData.userService.siteAreaApi,
+ Factory.siteArea.build({
+ siteID: testData.newSite.id
+ })
+ );
+ testData.createdSiteAreas.push(testData.newSiteArea);
+ expect(testData.newSiteArea).to.not.be.null;
+ // Create a new Asset
+ testData.newAsset = await testData.userService.createEntity(
+ testData.userService.assetApi,
+ Factory.asset.build({
+ siteAreaID: testData.newSiteArea.id,
+ assetType: 'CO-PR'
+ })
+ );
+ testData.createdAssets.push(testData.newAsset);
+ expect(testData.newAsset).to.not.be.null;
+ // Create a IoThink connection object in settings
+ const ioThinkAssetConnectorId = 100;
+ testData.newAssetConnector = await testData.userService.createEntity(
+ testData.userService.settingApi,
+ Factory.setting.build({
+ identifier: 'asset',
+ content: {
+ type: 'asset',
+ asset: {
+ connections: [{
+ id: ioThinkAssetConnectorId,
+ name: 'ioThink Asset Connector',
+ description: 'IoThink Asset Connector',
+ url: 'https://api.kheiron-sp.io',
+ type: 'iothink',
+ refreshIntervalMins: 1,
+ }]
+ }
+ }
+ })
+ );
+ });
+
+ // Should be able to fetch values from IoThink asset
+
+ // Should be able to fetch values form Wit asset
+
+ });
+});

MODIFY
test/api/AssetTest.ts
test/api/AssetTest.ts
+import { AssetConnectionType, AssetSettingsType, SettingDB } from '../../src/types/Setting';
import chai, { expect } from 'chai';
import Asset from '../../src/types/Asset';
@@ -5,12 +6,16 @@ import CentralServerService from './client/CentralServerService';
import Company from '../../src/types/Company';
import ContextDefinition from './context/ContextDefinition';
import ContextProvider from './context/ContextProvider';
+import Cypher from '../../src/utils/Cypher';
import Factory from '../factories/Factory';
import Site from '../../src/types/Site';
import SiteArea from '../../src/types/SiteArea';
import { StatusCodes } from 'http-status-codes';
+import { TenantComponents } from '../../src/types/Tenant';
import TenantContext from './context/TenantContext';
import chaiSubset from 'chai-subset';
+import config from '../config';
+import { l } from 'i18n-js';
chai.use(chaiSubset);
@@ -28,6 +33,7 @@ class TestData {
public createdSiteAreas: SiteArea[] = [];
public newAsset: Asset;
public createdAssets: Asset[] = [];
+ public ioThinkAssetConnectorID: string;
}
const testData: TestData = new TestData();
@@ -142,6 +148,21 @@ describe('Asset', function() {
expect(testData.newSiteArea).to.not.be.null;
});
+ after(async () => {
+ await testData.userService.deleteEntity(
+ testData.userService.siteAreaApi,
+ testData.newSiteArea
+ );
+ await testData.userService.deleteEntity(
+ testData.userService.siteApi,
+ testData.newSite
+ );
+ await testData.userService.deleteEntity(
+ testData.userService.companyApi,
+ testData.newCompany
+ );
+ });
+
it('Should be able to create a new Asset', async () => {
// Create
testData.newAsset = await testData.userService.createEntity(
@@ -239,6 +260,140 @@ describe('Asset', function() {
expect(response.status).to.be.eq(StatusCodes.OK);
expect(response.data.count).to.be.eq(1);
});
+
+ });
+
+ describe('Where admin user with asset ', () => {
+
+ before(async () => {
+ testData.userContext = testData.tenantContext.getUserContext(ContextDefinition.USER_CONTEXTS.DEFAULT_ADMIN);
+ if (testData.userContext === testData.centralUserContext) {
+ // Reuse the central user service (to avoid double login)
+ testData.userService = testData.centralUserService;
+ } else {
+ testData.userService = new CentralServerService(
+ testData.tenantContext.getTenant().subdomain,
+ testData.userContext
+ );
+ }
+ // Create a new Company
+ testData.newCompany = await testData.userService.createEntity(
+ testData.userService.companyApi,
+ Factory.company.build()
+ );
+ testData.createdCompanies.push(testData.newCompany);
+ expect(testData.newCompany).to.not.be.null;
+ // Create a new Site
+ testData.newSite = await testData.userService.createEntity(
+ testData.userService.siteApi,
+ Factory.site.build({
+ companyID: testData.newCompany.id
+ })
+ );
+ testData.createdSites.push(testData.newSite);
+ expect(testData.newSite).to.not.be.null;
+ // Create a new Site Area
+ testData.newSiteArea = await testData.userService.createEntity(
+ testData.userService.siteAreaApi,
+ Factory.siteArea.build({
+ siteID: testData.newSite.id
+ })
+ );
+ testData.createdSiteAreas.push(testData.newSiteArea);
+ expect(testData.newSiteArea).to.not.be.null;
+ // Create a new Asset
+ testData.newAsset = await testData.userService.createEntity(
+ testData.userService.assetApi,
+ Factory.asset.build({
+ siteAreaID: testData.newSiteArea.id,
+ assetType: 'PR'
+ })
+ );
+ testData.createdAssets.push(testData.newAsset);
+ expect(testData.newAsset).to.not.be.null;
+ });
+
+ after(async () => {
+ await testData.userService.deleteEntity(
+ testData.userService.assetApi,
+ testData.newAsset
+ );
+ await testData.userService.deleteEntity(
+ testData.userService.siteAreaApi,
+ testData.newSiteArea
+ );
+ await testData.userService.deleteEntity(
+ testData.userService.siteApi,
+ testData.newSite
+ );
+ await testData.userService.deleteEntity(
+ testData.userService.companyApi,
+ testData.newCompany
+ );
+ });
+
+ it('Should be able to create an ioThink asset connector', async () => {
+ const settings = await testData.centralUserService.settingApi.readAll({});
+ let newSetting = false;
+ let setting: SettingDB = settings.data.result.find((s) => s.identifier === TenantComponents.ASSET);
+ if (!setting) {
+ setting = {} as SettingDB;
+ setting.identifier = TenantComponents.ASSET;
+ newSetting = true;
+ }
+ const settingID = '0123456789abcdef';
+ setting.content = {
+ type: AssetSettingsType.ASSET,
+ asset: {
+ connections: [{
+ id: settingID,
+ name: 'Testing IoThink Asset Connector',
+ description: 'Testing IoThink Asset Connector',
+ url: config.get('assetConnectors.ioThink.url'),
+ timestamp: (new Date()),
+ type: AssetConnectionType.IOTHINK,
+ refreshIntervalMins: 1,
+ iothinkConnection: {
+ user: config.get('assetConnectors.ioThink.user'),
+ password: config.get('assetConnectors.ioThink.password')
+ }
+ }]
+ }
+ };
+ setting.sensitiveData = ['content.asset.connections[0].iothinkConnection.password'];
+ if (newSetting) {
+ await testData.centralUserService.settingApi.create(setting);
+ }
+ await testData.centralUserService.settingApi.update(setting);
+ const settingsUpdated = await testData.centralUserService.settingApi.readAll({});
+ const settingUpdated: SettingDB = settingsUpdated.data.result.find((s) => s.identifier === TenantComponents.ASSET);
+ expect(settingUpdated.content.asset.connections[0].id).to.be.eq(settingID);
+ testData.ioThinkAssetConnectorID = settingID;
+ });
+
+ it('should be able to connect ioThink asset connector connection', async () => {
+ const response = await testData.centralUserService.assetApi.checkAssetConnectorLink(testData.ioThinkAssetConnectorID);
+ expect(response.data?.status).to.be.eq('Success');
+ expect(response.data?.connectionIsValid).to.be.eq(true);
+ });
+
+ it('should be able to connect existing asset to asset connector', async () => {
+ // Change entity
+ testData.newAsset.dynamicAsset = true;
+ testData.newAsset.meterID = config.get('assetConnectors.ioThink.meterID');
+ testData.newAsset.connectionID = testData.ioThinkAssetConnectorID;
+ // Update
+ await testData.userService.updateEntity(
+ testData.userService.assetApi,
+ testData.newAsset
+ );
+ });
+
+ it('should be able to retrieve latest consumption', async () => {
+ const response = await testData.centralUserService.assetApi.retrieveLatestConsumption(testData.newAsset.id);
+ expect(response.data?.status).to.be.eq('Success');
+ });
+
});
});
});

MODIFY
test/api/client/AssetApi.ts
test/api/client/AssetApi.ts
+import { ServerAction, ServerRoute } from '../../../src/types/Server';
+
import Asset from '../../../src/types/Asset';
import AuthenticatedBaseApi from './utils/AuthenticatedBaseApi';
import CrudApi from './utils/CrudApi';
-import { ServerRoute } from '../../../src/types/Server';
import TestConstants from './utils/TestConstants';
export default class AssetApi extends CrudApi {
@@ -32,4 +33,13 @@ export default class AssetApi extends CrudApi {
public async readAllInError(params, paging = TestConstants.DEFAULT_PAGING, ordering = TestConstants.DEFAULT_ORDERING): Promise<any> {
return super.readAll(params, paging, ordering, this.buildRestEndpointUrl(ServerRoute.REST_ASSETS_IN_ERROR));
}
+
+ public async checkAssetConnectorLink(id): Promise<any> {
+ return super.read(id, this.buildRestEndpointUrl(ServerRoute.REST_ASSET_CHECK_CONNECTION, { id }));
+ }
+
+ public async retrieveLatestConsumption(id): Promise<any> {
+ return super.read(id, this.buildRestEndpointUrl(ServerRoute.REST_ASSET_RETRIEVE_CONSUMPTION, { id }));
+ }
+
}

MODIFY
test/config.js
test/config.js
@@ -333,6 +333,30 @@ const config = convict({
format: Number,
default: ''
}
+ },
+ assetConnectors: {
+ ioThink: {
+ user: {
+ doc: 'IoThink asset connector username',
+ format: String,
+ default: ''
+ },
+ password: {
+ doc: 'IoThink asset connector password',
+ format: String,
+ default: ''
+ },
+ url: {
+ doc: 'IoThink asset connector URL',
+ format: String,
+ default: 'https://api.kheiron-sp.io'
+ },
+ meterID: {
+ doc: 'Meter ID to connect asset to',
+ format: String,
+ default: ''
+ }
+ }
}
});

Changes for IoThink test cases