in internal/engine/common/scenario.go [95:217]
func CreateScenarioFromMarkdown(
path string,
languagesToExecute []string,
environmentVariableOverrides map[string]string,
) (*Scenario, error) {
source, err := resolveMarkdownSource(path)
if err != nil {
return nil, err
}
// Load environment variables
markdownINI := strings.TrimSuffix(path, filepath.Ext(path)) + ".ini"
environmentVariables := make(map[string]string)
// Check if the INI file exists & load it.
if !fs.FileExists(markdownINI) {
logging.GlobalLogger.Infof("INI file '%s' does not exist, skipping...", markdownINI)
} else {
logging.GlobalLogger.Infof("INI file '%s' exists, loading...", markdownINI)
environmentVariables, err = parsers.ParseINIFile(markdownINI)
if err != nil {
return nil, err
}
for key, value := range environmentVariables {
logging.GlobalLogger.Debugf("Setting %s=%s\n", key, value)
}
}
// Convert the markdonw into an AST and extract the scenario variables.
markdown := parsers.ParseMarkdownIntoAst(source)
properties := parsers.ExtractYamlMetadataFromAst(markdown)
scenarioVariables := parsers.ExtractScenarioVariablesFromAst(markdown, source)
for key, value := range scenarioVariables {
environmentVariables[key] = value
}
// Extract the code blocks from the markdown file.
codeBlocks := parsers.ExtractCodeBlocksFromAst(markdown, source, languagesToExecute)
logging.GlobalLogger.WithField("CodeBlocks", codeBlocks).
Debugf("Found %d code blocks", len(codeBlocks))
varsToExport := lib.CopyMap(environmentVariableOverrides)
for key, value := range environmentVariableOverrides {
environmentVariables[key] = value
logging.GlobalLogger.Debugf("Attempting to override %s with %s", key, value)
exportRegex := patterns.ExportVariableRegex(key)
for index, codeBlock := range codeBlocks {
matches := exportRegex.FindAllStringSubmatch(codeBlock.Content, -1)
if len(matches) != 0 {
logging.GlobalLogger.Debugf(
"Found %d matches for %s, deleting from varsToExport",
len(matches),
key,
)
delete(varsToExport, key)
} else {
logging.GlobalLogger.Debugf("Found no matches for %s inside of %s", key, codeBlock.Content)
}
for _, match := range matches {
oldLine := match[0]
oldValue := match[1]
// Replace the old export with the new export statement
newLine := strings.Replace(oldLine, oldValue, value+" ", 1)
logging.GlobalLogger.Debugf("Replacing '%s' with '%s'", oldLine, newLine)
// Update the code block with the new export statement
codeBlocks[index].Content = strings.Replace(codeBlock.Content, oldLine, newLine, 1)
}
}
}
// If there are some variables left after going through each of the codeblocks,
// do not update the scenario
// steps.
if len(varsToExport) != 0 {
logging.GlobalLogger.Debugf(
"Found %d variables to add to the scenario as a step.",
len(varsToExport),
)
exportCodeBlock := parsers.CodeBlock{
Language: "bash",
Content: "",
Header: "Exporting variables defined via the CLI and not in the markdown file.",
ExpectedOutput: parsers.ExpectedOutputBlock{},
}
for key, value := range varsToExport {
exportCodeBlock.Content += fmt.Sprintf("export %s=\"%s\"\n", key, value)
}
codeBlocks = append([]parsers.CodeBlock{exportCodeBlock}, codeBlocks...)
}
// Group the code blocks into steps.
steps := groupCodeBlocksIntoSteps(codeBlocks)
// If no title is found, we simply use the name of the markdown file as
// the title of the scenario.
title, err := parsers.ExtractScenarioTitleFromAst(markdown, source)
if err != nil {
logging.GlobalLogger.Warnf(
"Failed to extract scenario title: '%s'. Using the name of the markdown as the scenario title",
err,
)
title = filepath.Base(path)
}
logging.GlobalLogger.Infof("Successfully built out the scenario: %s", title)
return &Scenario{
Name: title,
Environment: environmentVariables,
Steps: steps,
Properties: properties,
MarkdownAst: markdown,
Source: source,
}, nil
}