• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

fslev / cucumber-jutils / #287

05 May 2026 01:59PM UTC coverage: 87.5% (-1.9%) from 89.399%
#287

push

fslevoaca-ionos
Migrate to Java 17, JUnit Jupiter 6, and Mockito 5; refactor internals with modern Java idioms

73 of 84 new or added lines in 7 files covered. (86.9%)

4 existing lines in 1 file now uncovered.

245 of 280 relevant lines covered (87.5%)

0.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.14
/src/main/java/com/cucumber/utils/context/ScenarioVarsUtils.java
1
package com.cucumber.utils.context;
2

3
import com.cucumber.utils.context.vars.ScenarioVars;
4
import com.cucumber.utils.context.vars.ScenarioVarsParser;
5
import com.cucumber.utils.exceptions.InvalidScenarioVarFileType;
6
import io.jtest.utils.common.ResourceUtils;
7
import org.apache.logging.log4j.LogManager;
8
import org.apache.logging.log4j.Logger;
9

10
import javax.annotation.Nullable;
11
import java.io.IOException;
12
import java.io.UncheckedIOException;
13
import java.net.URISyntaxException;
14
import java.util.Arrays;
15
import java.util.HashSet;
16
import java.util.Map;
17
import java.util.Properties;
18
import java.util.Set;
19

20
import static com.cucumber.utils.context.vars.ScenarioVars.FileExtension.PROPERTIES;
21
import static com.cucumber.utils.context.vars.ScenarioVars.FileExtension.YAML;
22
import static com.cucumber.utils.context.vars.ScenarioVars.FileExtension.YML;
23
import static com.cucumber.utils.context.vars.ScenarioVars.FileExtension.varFileExtensions;
24

25
public final class ScenarioVarsUtils {
26

27
    private ScenarioVarsUtils() {
28
    }
29

30
    private static final Logger LOG = LogManager.getLogger();
1✔
31

32
    /**
33
     * Reads file content and substitutes any scenario variables ({@code #[var]}) and SpEL expressions ({@code #{...}}) inside it.
34
     */
35
    public static String parse(String filePath, ScenarioVars scenarioVars) {
36
        try {
37
            return ScenarioVarsParser.parse(ResourceUtils.read(filePath), scenarioVars).toString();
1✔
38
        } catch (IOException e) {
×
NEW
39
            throw new UncheckedIOException(e);
×
40
        }
41
    }
42

43
    /**
44
     * Recursively scans a directory and loads each supported file as one or more scenario variables.
45
     *
46
     * @return names of loaded variables
47
     */
48
    public static Set<String> loadScenarioVarsFromDir(String dirPath, ScenarioVars scenarioVars) {
49
        Set<String> vars = new HashSet<>();
1✔
50
        try {
51
            Set<String> filePaths = ResourceUtils.getFilesFromDir(dirPath, ScenarioVars.FileExtension.allExtensions());
1✔
52
            filePaths.forEach(filePath -> {
1✔
53
                try {
54
                    if (!vars.addAll(loadScenarioVarsFromFile(filePath, scenarioVars))) {
1✔
55
                        throw new RuntimeException(("""
1✔
56

57
                                Ambiguous loading of scenario variables from dir '%s'
58
                                File '%s' contains a variable or is named after a variable that was already set while traversing directory""")
59
                                .formatted(dirPath, filePath));
1✔
60
                    }
61
                } catch (InvalidScenarioVarFileType e) {
×
62
                    LOG.warn(e.getMessage());
×
63
                }
1✔
64
            });
1✔
65
        } catch (IOException e) {
1✔
66
            throw new UncheckedIOException(e);
1✔
NEW
67
        } catch (URISyntaxException e) {
×
UNCOV
68
            throw new RuntimeException(e);
×
69
        }
1✔
70
        LOG.debug("Loaded from dir '{}', scenario variables with the following names:\n{}", dirPath, vars);
1✔
71
        return vars;
1✔
72
    }
73

74
    /**
75
     * Loads scenario variables from a single file. Properties and YAML files are flattened into one variable per
76
     * key; other supported text files become a single variable named after the file.
77
     *
78
     * @return names of loaded variables
79
     */
80
    public static Set<String> loadScenarioVarsFromFile(String filePath, ScenarioVars scenarioVars) {
81
        if (filePath.endsWith(PROPERTIES.value())) {
1✔
82
            return loadVarsFromPropertiesFile(filePath, scenarioVars);
1✔
83
        }
84
        if (filePath.endsWith(YAML.value()) || filePath.endsWith(YML.value())) {
1✔
85
            return loadVarsFromYamlFile(filePath, scenarioVars);
1✔
86
        }
87
        if (Arrays.stream(varFileExtensions()).anyMatch(filePath::endsWith)) {
1✔
88
            return Set.of(loadFileAsScenarioVariable(filePath, scenarioVars, null));
1✔
89
        }
90
        throw new InvalidScenarioVarFileType();
1✔
91
    }
92

93
    public static String loadFileAsScenarioVariable(String filePath, ScenarioVars scenarioVars, @Nullable String varName) {
94
        try {
95
            String fileName = ResourceUtils.getFileName(filePath);
1✔
96
            if (Arrays.stream(varFileExtensions()).noneMatch(fileName::endsWith)) {
1✔
UNCOV
97
                throw new RuntimeException("Invalid file extension: " + filePath +
×
98
                        " .Must use one of the following: \"" + Arrays.toString(varFileExtensions()));
×
99
            }
100
            String key = varName == null ? extractSimpleName(fileName) : varName;
1✔
101
            String value = ResourceUtils.read(filePath);
1✔
102
            scenarioVars.put(key, value);
1✔
103
            LOG.debug("-> Loaded file '{}' into a scenario variable", filePath);
1✔
104
            return key;
1✔
105
        } catch (IOException e) {
1✔
106
            throw new UncheckedIOException(e);
1✔
NEW
107
        } catch (URISyntaxException e) {
×
UNCOV
108
            throw new RuntimeException(e);
×
109
        }
110
    }
111

112
    private static Set<String> loadVarsFromPropertiesFile(String filePath, ScenarioVars scenarioVars) {
113
        Properties p;
114
        try {
115
            p = ResourceUtils.readProps(filePath);
1✔
116
        } catch (IOException e) {
×
NEW
117
            throw new UncheckedIOException(e);
×
118
        }
1✔
119
        p.forEach((k, v) -> scenarioVars.put(k.toString(), v.toString().trim()));
1✔
120
        LOG.debug("-> Loaded scenario variables from file {}", filePath);
1✔
121
        return p.stringPropertyNames();
1✔
122
    }
123

124
    private static Set<String> loadVarsFromYamlFile(String filePath, ScenarioVars scenarioVars) {
125
        Map<String, Object> map;
126
        try {
127
            map = ResourceUtils.readYaml(filePath);
1✔
UNCOV
128
        } catch (IOException e) {
×
NEW
129
            throw new UncheckedIOException(e);
×
130
        }
1✔
131
        if (map == null) {
1✔
NEW
132
            throw new RuntimeException("Incorrect data inside Yaml file: " + filePath);
×
133
        }
134
        map.forEach(scenarioVars::put);
1✔
135
        LOG.debug("-> Loaded scenario variables from file '{}'", filePath);
1✔
136
        return map.keySet();
1✔
137
    }
138

139
    private static String extractSimpleName(String fileName) {
140
        return fileName.substring(0, fileName.lastIndexOf(".")).trim();
1✔
141
    }
142
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc