Skip to content

Commit d1130c5

Browse files
committed
Refactor option handling and extract common routines
1 parent ce73140 commit d1130c5

File tree

3 files changed

+56
-49
lines changed

3 files changed

+56
-49
lines changed

features/suite_only_options.feature

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ Feature: suite only options
7979
Then it fails
8080
And the output should contain
8181
"""
82-
Tag @testIsolation(false) can only be used on a Feature or a Rule
82+
Tag testIsolation can only be used on a Feature or a Rule
8383
"""
8484

8585
Scenario: Configuring testIsolation on a Scenario Outline
@@ -105,7 +105,7 @@ Feature: suite only options
105105
Then it fails
106106
And the output should contain
107107
"""
108-
Tag @testIsolation(false) can only be used on a Feature or a Rule
108+
Tag testIsolation can only be used on a Feature or a Rule
109109
"""
110110

111111
Scenario: Configuring testIsolation on Examples
@@ -131,5 +131,5 @@ Feature: suite only options
131131
Then it fails
132132
And the output should contain
133133
"""
134-
Tag @testIsolation(false) can only be used on a Feature or a Rule
134+
Tag testIsolation can only be used on a Feature or a Rule
135135
"""

lib/browser-runtime.ts

Lines changed: 21 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {
3434
HOOK_FAILURE_EXPR,
3535
INTERNAL_SPEC_PROPERTIES,
3636
INTERNAL_SUITE_PROPERTIES,
37-
TEST_ISOLATION_CONFIGURATION_OPTION,
3837
} from "./constants";
3938

4039
import {
@@ -66,6 +65,12 @@ import { getTags } from "./helpers/environment";
6665

6766
import { ICaseHookParameter, IStepHookParameter } from "./public-member-types";
6867

68+
import {
69+
isExclusivelySuiteConfiguration,
70+
isNotExclusivelySuiteConfiguration,
71+
tagsToOptions,
72+
} from "./helpers/options";
73+
6974
type Node = ReturnType<typeof parse>;
7075

7176
type TestStepIds = Map<string, Map<string, string>>;
@@ -288,13 +293,7 @@ function createStepDescription({
288293

289294
function createFeature(context: CompositionContext, feature: messages.Feature) {
290295
const suiteOptions = Object.fromEntries(
291-
collectTagNames(feature.tags)
292-
.filter(looksLikeOptions)
293-
.map(tagToCypressOptions)
294-
.filter(
295-
([property]) =>
296-
property === (TEST_ISOLATION_CONFIGURATION_OPTION as string)
297-
)
296+
tagsToOptions(feature.tags).filter(isExclusivelySuiteConfiguration)
298297
) as Cypress.TestConfigOverrides;
299298

300299
describe(feature.name || "<unamed feature>", suiteOptions, () => {
@@ -358,13 +357,7 @@ function createRule(context: CompositionContext, rule: messages.Rule) {
358357
}
359358

360359
const suiteOptions = Object.fromEntries(
361-
collectTagNames(rule.tags)
362-
.filter(looksLikeOptions)
363-
.map(tagToCypressOptions)
364-
.filter(
365-
([property]) =>
366-
property === (TEST_ISOLATION_CONFIGURATION_OPTION as string)
367-
)
360+
tagsToOptions(rule.tags).filter(isExclusivelySuiteConfiguration)
368361
) as Cypress.TestConfigOverrides;
369362

370363
describe(rule.name || "<unamed rule>", suiteOptions, () => {
@@ -458,51 +451,33 @@ function createPickle(context: CompositionContext, pickle: messages.Pickle) {
458451
"Expected a scenario to have a examples property"
459452
);
460453

461-
const tagsDefinedOnThisScenarioTagNameAstIdMap = scenario.tags.reduce(
462-
(acc, tag) => {
463-
acc[tag.name] = tag.id;
464-
return acc;
465-
},
466-
{} as Record<string, string>
467-
);
468-
469-
for (const example of scenario.examples) {
470-
example.tags.forEach((tag) => {
471-
tagsDefinedOnThisScenarioTagNameAstIdMap[tag.name] = tag.id;
472-
});
473-
}
454+
const testSpecificOptions = tagsToOptions([
455+
...scenario.tags,
456+
...scenario.examples.flatMap((example) => example.tags),
457+
]);
474458

475-
for (const tag of pickle.tags) {
476-
if (
477-
looksLikeOptions(tag.name) &&
478-
tagsDefinedOnThisScenarioTagNameAstIdMap[tag.name] === tag.astNodeId &&
479-
Object.keys(tagToCypressOptions(tag.name)).every(
480-
(key) => key === TEST_ISOLATION_CONFIGURATION_OPTION
481-
)
482-
) {
459+
for (const entry of testSpecificOptions) {
460+
if (isExclusivelySuiteConfiguration(entry)) {
483461
throw new Error(
484-
`Tag ${tag.name} can only be used on a Feature or a Rule`
462+
`Tag ${entry[0]} can only be used on a Feature or a Rule`
485463
);
486464
}
487465
}
488466

489-
const suiteOptions = Object.fromEntries(
467+
const inheritedTestOptions = Object.fromEntries(
490468
tags
491469
.filter(looksLikeOptions)
492470
.map(tagToCypressOptions)
493-
.filter(
494-
([property]) =>
495-
property !== (TEST_ISOLATION_CONFIGURATION_OPTION as string)
496-
)
471+
.filter(isNotExclusivelySuiteConfiguration)
497472
) as Cypress.TestConfigOverrides;
498473

499-
if (suiteOptions.env) {
500-
Object.assign(suiteOptions.env, internalEnv);
474+
if (inheritedTestOptions.env) {
475+
Object.assign(inheritedTestOptions.env, internalEnv);
501476
} else {
502-
suiteOptions.env = internalEnv;
477+
inheritedTestOptions.env = internalEnv;
503478
}
504479

505-
it(scenarioName, suiteOptions, function () {
480+
it(scenarioName, inheritedTestOptions, function () {
506481
const { remainingSteps, testCaseStartedId } =
507482
retrieveInternalSpecProperties();
508483

lib/helpers/options.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import * as messages from "@cucumber/messages";
2+
3+
import { collectTagNames } from "./ast";
4+
5+
import {
6+
ConfigurationEntry,
7+
looksLikeOptions,
8+
tagToCypressOptions,
9+
} from "./tag-parser";
10+
import { TEST_ISOLATION_CONFIGURATION_OPTION } from "../constants";
11+
12+
export function tagsToOptions(tags: readonly messages.Tag[]) {
13+
return collectTagNames(tags)
14+
.filter(looksLikeOptions)
15+
.map(tagToCypressOptions);
16+
}
17+
18+
export function isExclusivelySuiteConfiguration(entry: ConfigurationEntry) {
19+
// TODO: Remove type cast once support for v10 is removed.
20+
return entry[0] === (TEST_ISOLATION_CONFIGURATION_OPTION as string);
21+
}
22+
23+
export function isNotExclusivelySuiteConfiguration(entry: ConfigurationEntry) {
24+
// TODO: Remove type cast once support for v10 is removed.
25+
return entry[0] !== (TEST_ISOLATION_CONFIGURATION_OPTION as string);
26+
}
27+
28+
export function hasExclusivelySuiteConfiguration(
29+
config: Cypress.TestConfigOverrides
30+
) {
31+
return Object.keys(config).includes(TEST_ISOLATION_CONFIGURATION_OPTION);
32+
}

0 commit comments

Comments
 (0)