/* * Copyright (C) 2019-2022 Open StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ /* eslint-disable unicorn/prevent-abbreviations */ import {SCSearchRequest, SCThings, SCThingType} from '@openstapps/core'; import {Logger} from '@openstapps/logger'; import {deepStrictEqual} from 'assert'; import {readdir, readFile} from 'fs'; import path from 'path'; import {promisify} from 'util'; import {ConnectorClient} from './connector-client'; import {HttpClientInterface} from './http-client-interface'; const localItemMap: Map = new Map(); const remoteItemMap: Map = new Map(); /** * Options to set up indexing core test files to backend */ export interface E2EOptions { /** * File path of the directory containing core test files */ samplesLocation: string; /** * URL of the backend to index to */ to: string; } /** * Function that can be used for integration tests. * Adds all the SCThings that getItemsFromSamples() returns to the backend. * Afterwards retrieves the items from backend and checks for differences with original ones. */ export async function e2eRun(client: HttpClientInterface, options: E2EOptions): Promise { localItemMap.clear(); remoteItemMap.clear(); const api = new ConnectorClient(client, options.to); try { await indexSamples(api, options); Logger.info(`All samples have been indexed via the backend`); await retrieveItems(api); Logger.info(`All samples have been retrieved from the backend`); compareItems(); } catch (error) { throw error; } } /** * Retieves all samples previously index using the api */ async function retrieveItems(api: ConnectorClient): Promise { const singleItemSearchRequest: SCSearchRequest = { filter: { arguments: { field: 'uid', value: 'replace-me', }, type: 'value', }, }; for (const uid of localItemMap.keys()) { singleItemSearchRequest.filter!.arguments.value = uid; const searchResonse = await api.search(singleItemSearchRequest); if (searchResonse.data.length !== 1) { throw new Error( `Search for single SCThing with uid: ${uid} returned ${searchResonse.data.length} results`, ); } remoteItemMap.set(uid, searchResonse.data[0]); } } /** * Compares all samples (local and remote) with the same uid and throws if they're not deep equal */ function compareItems() { for (const localThing of localItemMap.values()) { /* istanbul ignore next retrieveItems will throw before*/ if (!remoteItemMap.has(localThing.uid)) { throw new Error(`Did not retrieve expected SCThing with uid: ${localThing.uid}`); } const remoteThing = remoteItemMap.get(localThing.uid); deepStrictEqual(remoteThing, localThing, `Unexpected difference between original and retrieved sample`); } Logger.info( `All samples retrieved from the backend are the same (deep equal) as the original ones submitted`, ); } /** * Function to add all the SCThings that getItemsFromSamples() returns to the backend */ async function indexSamples(api: ConnectorClient, options: E2EOptions): Promise { try { const items = await getItemsFromSamples(options.samplesLocation); if (items.length === 0) { throw new Error('Could not index samples. None were retrieved from the file system.'); } // sort items by type const itemMap: Map = new Map(); for (const item of items) { if (!itemMap.has(item.type)) { itemMap.set(item.type, []); } const itemsOfSameType = itemMap.get(item.type) as SCThings[]; itemsOfSameType.push(item); itemMap.set(item.type, itemsOfSameType); localItemMap.set(item.uid, item); } // add items depending on their type property with one type per bulk for (const type of itemMap.keys()) { await api.index(itemMap.get(type) as SCThings[], 'stapps-core-sample-data'); } } catch (error) { throw error; } } /** * Get all SCThings from the predefined core test json files * * @param samplesDirectory Filepath to the directory containing to the core test json files * @returns an Array of all the SCThings specified for test usage */ export async function getItemsFromSamples(samplesDirectory: string): Promise { const readDirPromised = promisify(readdir); const readFilePromised = promisify(readFile); const things: T[] = []; try { const fileNames = await readDirPromised(samplesDirectory); for (const fileName of fileNames) { const filePath = path.join(samplesDirectory, fileName); if (filePath.endsWith('.json')) { const fileContent = await readFilePromised(filePath, {encoding: 'utf8'}); const schemaObject = JSON.parse(fileContent); if (schemaObject.errorNames.length === 0 && typeof schemaObject.instance.type === 'string') { things.push(schemaObject.instance); } } } } catch (error) { throw error; } return things; }