-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Wrap SiteWise Asset related API calls in a Data Source
* Created a DataSource for SiteWise assets module to use. This scopes down what the asset modules can get at from the raw API. * Use RequestProcessorWorkerGroup for every request in RequestProcessor, not any simultaneous requests for the same data item will result in only 1 API call. * Unit testing for the RequestProcessor and RequestProcessorWorkerGroup * Raise coverage limits back up to 80% * Changed the base class for RequestProcessWorker to ReplaySubject. This stops an initial 'empty' value from being sent to the caller which could be confusing and made programming more complex for the non-list use-case.
- Loading branch information
1 parent
ffbbe19
commit b9eabc2
Showing
13 changed files
with
664 additions
and
122 deletions.
There are no files selected for viewing
159 changes: 155 additions & 4 deletions
159
packages/core/src/asset-modules/sitewise/requestProcessor.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,160 @@ | ||
import { RequestProcessor } from './requestProcessor'; | ||
import { IoTSiteWiseClient } from '@aws-sdk/client-iotsitewise'; | ||
import { SiteWiseAssetCache } from './cache'; | ||
import { SiteWiseAssetDataSource } from '../../data-module/types'; | ||
import { | ||
AssetSummary, | ||
AssetPropertyValue, | ||
DescribeAssetCommandInput, | ||
DescribeAssetCommandOutput, | ||
DescribeAssetModelResponse, | ||
DescribeAssetModelCommandInput, | ||
DescribeAssetModelCommandOutput, | ||
GetAssetPropertyValueCommandInput, | ||
GetAssetPropertyValueCommandOutput, | ||
ListAssetsCommandInput, | ||
ListAssetsCommandOutput, | ||
ListAssociatedAssetsCommandInput, | ||
ListAssociatedAssetsCommandOutput, | ||
} from '@aws-sdk/client-iotsitewise'; | ||
import { Observable } from 'rxjs'; | ||
import { sampleAssetModel, sampleAssetSummary, samplePropertyValue } from '../mocks.spec'; | ||
import { HIERARCHY_ROOT_ID, HierarchyAssetSummaryList, LoadingStateEnum } from './types'; | ||
|
||
it('initializes', () => { | ||
expect( | ||
() => new RequestProcessor(new IoTSiteWiseClient({ region: 'us-east' }), new SiteWiseAssetCache()) | ||
).not.toThrowError(); | ||
expect(() => { | ||
new RequestProcessor({} as SiteWiseAssetDataSource, new SiteWiseAssetCache()); | ||
}).not.toThrowError(); | ||
}); | ||
|
||
const createMockSiteWiseAssetDataSource = (): SiteWiseAssetDataSource => { | ||
return { | ||
describeAsset: (input: DescribeAssetCommandInput): Promise<DescribeAssetCommandOutput> => { | ||
throw 'No Calls Expected'; | ||
}, | ||
|
||
getPropertyValue: (input: GetAssetPropertyValueCommandInput): Promise<GetAssetPropertyValueCommandOutput> => { | ||
throw 'No Calls Expected'; | ||
}, | ||
|
||
describeAssetModel: (input: DescribeAssetModelCommandInput): Promise<DescribeAssetModelCommandOutput> => { | ||
throw 'No Calls Expected'; | ||
}, | ||
|
||
listAssets: (input: ListAssetsCommandInput): Promise<ListAssetsCommandOutput> => { | ||
throw 'No Calls Expected'; | ||
}, | ||
|
||
listAssociatedAssets: (input: ListAssociatedAssetsCommandInput): Promise<ListAssociatedAssetsCommandOutput> => { | ||
throw 'No Calls Expected'; | ||
}, | ||
}; | ||
}; | ||
|
||
describe('Request an AssetSummary', () => { | ||
const mockDataSource = createMockSiteWiseAssetDataSource(); | ||
let mockDescribeAsset = jest.fn(); | ||
mockDescribeAsset.mockReturnValue(Promise.resolve(sampleAssetSummary)); | ||
mockDataSource.describeAsset = mockDescribeAsset; | ||
|
||
const requestProcessor: RequestProcessor = new RequestProcessor(mockDataSource, new SiteWiseAssetCache()); | ||
const observable: Observable<AssetSummary> = new Observable<AssetSummary>((observer) => { | ||
requestProcessor.getAssetSummary({ assetId: sampleAssetSummary.id as string }, observer); | ||
}); | ||
|
||
it('waits for the AssetSummary', (done) => { | ||
observable.subscribe((result) => { | ||
expect(result).not.toBeUndefined(); | ||
expect(result).toEqual(sampleAssetSummary); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('Request an Asset Model', () => { | ||
const mockDataSource = createMockSiteWiseAssetDataSource(); | ||
let mockDescribeAssetModel = jest.fn(); | ||
mockDescribeAssetModel.mockReturnValue(Promise.resolve(sampleAssetModel)); | ||
mockDataSource.describeAssetModel = mockDescribeAssetModel; | ||
|
||
const requestProcessor: RequestProcessor = new RequestProcessor(mockDataSource, new SiteWiseAssetCache()); | ||
const observable: Observable<DescribeAssetModelResponse> = new Observable<DescribeAssetModelResponse>((observer) => { | ||
requestProcessor.getAssetModel({ assetModelId: sampleAssetModel.assetModelId as string }, observer); | ||
}); | ||
|
||
it('waits for the Asset Model', (done) => { | ||
observable.subscribe((result) => expect(sampleAssetModel).toEqual(result)); | ||
done(); | ||
}); | ||
}); | ||
|
||
describe('Request an Asset Property Value', () => { | ||
const mockDataSource = createMockSiteWiseAssetDataSource(); | ||
let mockGetPropertyValue = jest.fn(); | ||
mockGetPropertyValue.mockReturnValue(Promise.resolve(samplePropertyValue)); | ||
mockDataSource.getPropertyValue = mockGetPropertyValue; | ||
|
||
const requestProcessor: RequestProcessor = new RequestProcessor(mockDataSource, new SiteWiseAssetCache()); | ||
const observable: Observable<AssetPropertyValue> = new Observable<AssetPropertyValue>((observer) => { | ||
requestProcessor.getAssetPropertyValue( | ||
{ | ||
assetId: sampleAssetSummary.id as string, | ||
propertyId: 'doesnt matter', | ||
}, | ||
observer | ||
); | ||
}); | ||
|
||
it('waits for the Asset Property Value', (done) => { | ||
observable.subscribe((result) => expect(samplePropertyValue).toEqual(result)); | ||
done(); | ||
}); | ||
}); | ||
|
||
describe('Request an Asset Hierarchy of a parent Asset', () => { | ||
const mockDataSource = createMockSiteWiseAssetDataSource(); | ||
const mockListAssociatedAssets = jest.fn(); | ||
const result: ListAssetsCommandOutput = { $metadata: {}, assetSummaries: [sampleAssetSummary] }; | ||
mockListAssociatedAssets.mockReturnValue(Promise.resolve<ListAssetsCommandOutput>(result)); | ||
mockDataSource.listAssociatedAssets = mockListAssociatedAssets; | ||
const requestProcessor: RequestProcessor = new RequestProcessor(mockDataSource, new SiteWiseAssetCache()); | ||
const observable: Observable<HierarchyAssetSummaryList> = new Observable<HierarchyAssetSummaryList>((observer) => { | ||
requestProcessor.getAssetHierarchy({ assetId: 'parentAssetId', assetHierarchyId: 'hierarchyId' }, observer); | ||
}); | ||
|
||
it('waits for the Asset Hierarchy to become loaded', (done) => { | ||
observable.subscribe((result) => { | ||
// the worker returns the completed list of assets: | ||
expect({ | ||
assetHierarchyId: 'hierarchyId', | ||
assets: [sampleAssetSummary], | ||
loadingState: LoadingStateEnum.LOADED, | ||
}).toEqual(result); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('Request the root assets', () => { | ||
const mockDataSource = createMockSiteWiseAssetDataSource(); | ||
const mockListAssets = jest.fn(); | ||
const result: ListAssetsCommandOutput = { $metadata: {}, assetSummaries: [sampleAssetSummary] }; | ||
mockListAssets.mockReturnValue(Promise.resolve<ListAssetsCommandOutput>(result)); | ||
mockDataSource.listAssets = mockListAssets; | ||
const requestProcessor: RequestProcessor = new RequestProcessor(mockDataSource, new SiteWiseAssetCache()); | ||
|
||
const observable: Observable<HierarchyAssetSummaryList> = new Observable<HierarchyAssetSummaryList>((observer) => { | ||
requestProcessor.getAssetHierarchy({ assetHierarchyId: HIERARCHY_ROOT_ID }, observer); | ||
}); | ||
|
||
it('waits for the root assets to become loaded', (done) => { | ||
observable.subscribe((result) => { | ||
// the worker returns the completed list of assets: | ||
expect({ | ||
assetHierarchyId: HIERARCHY_ROOT_ID, | ||
assets: [sampleAssetSummary], | ||
loadingState: LoadingStateEnum.LOADED, | ||
}).toEqual(result); | ||
done(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.