diff --git a/mock/mock.ts b/mock/mock.ts index 0712a43..94cdfd4 100644 --- a/mock/mock.ts +++ b/mock/mock.ts @@ -4,7 +4,7 @@ import * as protoLoader from "@grpc/proto-loader"; import path, { resolve } from "path"; import { ProtoGrpcType } from "../proto/services"; import Mode, { MODE_TEST } from "../src/mode"; -import { createExecutionContext, getExecutionContext } from "../src/context"; +import { createExecutionContext } from "../src/context"; import { startRecordingMocks } from "./utils"; const PORT = 6789; @@ -26,12 +26,26 @@ export interface Config { Path: string; Mode: string; } -export function NewContext(conf: Config) { + +// NewContext is used to populate the context to mock/capture the dependency calls. +// Since, grpc unary calls are made, Promise is returned to sync the outputs +// before the external dependency calls from unit tests. +export function NewContext(conf: Config): Promise { const mode = new Mode(); - let path = conf !== undefined && conf.Path !== undefined ? conf.Path : ""; - // default mode: TEST + // default mode should be TEST mode.SetMode(MODE_TEST); + if ( + process.env.KEPLOY_MODE !== undefined && + Mode.Valid(process.env.KEPLOY_MODE) + ) { + mode.SetMode(process.env.KEPLOY_MODE); + } + // mode mostly dependent on conf.Mode + if (Mode.Valid(conf.Mode)) { + mode.SetMode(conf.Mode); + } + let path = conf !== undefined && conf.Path !== undefined ? conf.Path : ""; if (path === "") { try { path = process.cwd(); @@ -50,53 +64,6 @@ export function NewContext(conf: Config) { path += "/mocks"; mockPath = path; - if ( - process.env.KEPLOY_MODE !== undefined && - Mode.Valid(process.env.KEPLOY_MODE) - ) { - // if (process.) - mode.SetMode(process.env.KEPLOY_MODE); - } - // mode mostly dependent on conf.Mode - if (Mode.Valid(conf.Mode)) { - mode.SetMode(conf.Mode); - } - switch (mode.GetMode()) { - case "test": - if (conf.Name === "") { - console.log( - "🚨 Please enter the auto generated name to mock the dependencies using Keploy." - ); - } - createExecutionContext({ - mode: mode.GetMode(), - testId: conf.Name, - mocks: [], - fileExport: true, - }); - const ctx = getExecutionContext().context; - grpcClient.GetMocks({ Path: path, Name: conf.Name }, (err, response) => { - if (err) { - console.error(err); - return; - } - ctx.mocks = response?.Mocks; - return response; - }); - break; - case "record": - createExecutionContext({ - mode: mode.GetMode(), - testId: conf.Name, - mocks: [], - fileExport: true, - }); - break; - default: - console.log("Keploy mode: (", mode.GetMode(), ") is not a valid mode"); - break; - } - let name = ""; if (conf.Name !== "") { name = "for " + conf.Name; @@ -108,10 +75,57 @@ export function NewContext(conf: Config) { name, ".\n If you dont see any logs about your dependencies below, your dependency/s are NOT wrapped.\n" ); - startRecordingMocks( - path + "/" + conf.Name + ".yaml", - mode.GetMode(), - name, - conf.Name - ); + const ctx: { mode: string; testId: string; fileExport: boolean; mocks: any } = + { + mode: mode.GetMode(), + testId: conf.Name, + fileExport: true, + mocks: [], + }; + switch (mode.GetMode()) { + case "test": + if (conf.Name === "") { + console.log( + "🚨 Please enter the auto generated name to mock the dependencies using Keploy." + ); + } + createExecutionContext(ctx); + case "record": + createExecutionContext(ctx); + } + + // returns Promise to sync the outputs from the grpc unary calls + return new Promise((rsolve, reject) => { + switch (mode.GetMode()) { + case "test": + grpcClient.GetMocks( + { Path: path, Name: conf.Name }, + (err, response) => { + if (err) { + console.error(err); + reject(err); + return; + } + ctx.mocks = response?.Mocks; + rsolve("passed"); + return response; + } + ); + break; + case "record": + startRecordingMocks( + path + "/" + conf.Name + ".yaml", + mode.GetMode(), + name, + conf.Name, + rsolve, + reject + ); + break; + default: + console.log("Keploy mode: (", mode.GetMode(), ") is not a valid mode"); + reject(`Keploy mode: (${mode.GetMode()}) is not a valid mode`); + break; + } + }); } diff --git a/mock/utils.ts b/mock/utils.ts index cbeee52..5a7ae64 100644 --- a/mock/utils.ts +++ b/mock/utils.ts @@ -1,4 +1,3 @@ -import { response } from "express"; import { Mock } from "../proto/services/Mock"; import { grpcClient, MockIds, mockPath } from "./mock"; @@ -20,7 +19,9 @@ export function startRecordingMocks( path: string, mode: string, name: string, - mockId: string + mockId: string, + resolve: (value: string | PromiseLike) => void, + reject: (reason?: string) => void ) { grpcClient.StartMocking( { @@ -30,6 +31,7 @@ export function startRecordingMocks( function (err, response) { if (err !== null) { console.error("failed to start mocking due to error: ", err); + reject(`failed to start mocking due to error: ${err}`); return; } if (response?.Exists) { @@ -42,6 +44,7 @@ export function startRecordingMocks( ); MockIds[mockId] = true; } + resolve("Passed"); } ); } diff --git a/src/context.ts b/src/context.ts index 120fdac..6bb2d97 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable @typescript-eslint/no-explicit-any */ import asyncHooks from "async_hooks"; const executionContextMap = new Map(); @@ -7,14 +5,14 @@ const executionContextMap = new Map(); const asyncHook = asyncHooks.createHook({ init, destroy }); asyncHook.enable(); -function init(asyncId: any, type: any, triggerAsyncId: any) { +function init(asyncId: number, type: string, triggerAsyncId: number) { const parentContext = executionContextMap.get(triggerAsyncId); if (!parentContext) return; executionContextMap.set(asyncId, { context: parentContext.context }); } -function destroy(asyncId: any) { +function destroy(asyncId: number) { executionContextMap.delete(asyncId); }