Karate: [feature-consideration] ability to Inject configuration file content as String in ScenarioContext

Created on 9 Nov 2018  路  2Comments  路  Source: intuit/karate

@ptrthomas I see there is a configuration script loading sequence in the ScenarioContext.

It is a little bit complicated sequence I know.
If I make a modification CallContext to carry callContext.configurationContent String and carry to ScenarioContext and let it evaluate during Script.callAndUpdateConfigAndAlsoVarsIfMapReturned sequence. is that kind of modification you mind seeing it? If you don't mind, I can work on it and do pull request. maybe take out configuration loading logic and provide some kind of static factory..

 public ScenarioContext(FeatureContext featureContext, CallContext call) {
        this.featureContext = featureContext; // make sure references below to env.env use the updated one
        logger = featureContext.logger;
        callDepth = call.callDepth;
        reuseParentContext = call.reuseParentContext;
        executionHook = call.executionHook;
        perfMode = call.perfMode;
        tags = call.getTags().getTags();
        tagValues = call.getTags().getTagValues();
        scenarioInfo = call.getScenarioInfo();
        if (reuseParentContext) {
            parentContext = call.context;
            vars = call.context.vars; // shared context !
            config = call.context.config;
            rootFeatureContext = call.context.rootFeatureContext;
            driver = call.context.driver;
            webSocketClients = call.context.webSocketClients;
        } else if (call.context != null) {
            parentContext = call.context;
            // complex objects like JSON and XML are "global by reference" TODO           
            vars = call.context.vars.copy(false);
            config = new HttpConfig(call.context.config);
            rootFeatureContext = call.context.rootFeatureContext;
        } else {
            parentContext = null;
            vars = new ScriptValueMap();
            config = new HttpConfig();
            config.setClientClass(call.httpClientClass);
            rootFeatureContext = featureContext;
        }
        client = HttpClient.construct(config, this);
        bindings = new ScriptBindings(this);
        if (call.context == null && call.evalKarateConfig) {
            // base config is only looked for in the classpath
            try {
                Script.callAndUpdateConfigAndAlsoVarsIfMapReturned(false, ScriptBindings.READ_KARATE_CONFIG_BASE, null, this);
            } catch (Exception e) {
                if (e instanceof KarateFileNotFoundException) {
                    logger.trace("skipping 'classpath:karate-base.js': {}", e.getMessage());
                } else {
                    throw new RuntimeException("evaluation of 'classpath:karate-base.js' failed", e);
                }
            }
            String configDir = System.getProperty(ScriptBindings.KARATE_CONFIG_DIR);
            String configScript = ScriptBindings.readKarateConfigForEnv(true, configDir, null);
            try {
                Script.callAndUpdateConfigAndAlsoVarsIfMapReturned(false, configScript, null, this);
            } catch (Exception e) {
                if (e instanceof KarateFileNotFoundException) {
                    logger.warn("skipping bootstrap configuration: {}", e.getMessage());
                } else {
                    throw new RuntimeException("evaluation of '" + ScriptBindings.KARATE_CONFIG_JS + "' failed", e);
                }
            }
            if (featureContext.env != null) {
                configScript = ScriptBindings.readKarateConfigForEnv(false, configDir, featureContext.env);
                try {
                    Script.callAndUpdateConfigAndAlsoVarsIfMapReturned(false, configScript, null, this);
                } catch (Exception e) {
                    if (e instanceof KarateFileNotFoundException) {
                        logger.trace("skipping bootstrap configuration for env: {} - {}", featureContext.env, e.getMessage());
                    } else {
                        throw new RuntimeException("evaluation of 'karate-config-" + featureContext.env + ".js' failed", e);
                    }
                }
            }
        }

        //String content of Configuration loading condition here.

        if (call.callArg != null) { // if call.reuseParentContext is true, arg will clobber parent context
            for (Map.Entry<String, Object> entry : call.callArg.entrySet()) {
                vars.put(entry.getKey(), entry.getValue());
            }
            vars.put(Script.VAR_ARG, call.callArg);
            vars.put(Script.VAR_LOOP, call.loopIndex);
        } else if (call.context != null) {
            vars.put(Script.VAR_ARG, ScriptValue.NULL);
            vars.put(Script.VAR_LOOP, -1);
        }
        logger.trace("karate context init - initial properties: {}", vars);
    }
question

All 2 comments

if you just need to inject extra custom variables I propose this. the CallContext has a callArg Map - and all key-values will be injected like you see above at the end. maybe that will suffice for you ? even if you have a JS function, you should be able to eval it and get the result Map

yes this code is already complicated - and runs before every Scenario and Examples row

oh ok, I did not think about that. eval(configurationContent) could do the job.
thanks

Was this page helpful?
0 / 5 - 0 ratings