Skip to content

Commit

Permalink
refactored glob patterns used to retrieve variable files and replaced…
Browse files Browse the repository at this point in the history
… primitive array methods with performant babel macros that transform to inline loops and changed temp folder to use the os temp folder path and updated docs accordingly
  • Loading branch information
mainfraame committed Feb 24, 2021
1 parent 9a8b01d commit b66fc41
Show file tree
Hide file tree
Showing 17 changed files with 359 additions and 327 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.3] - 2021-02-24

### Added

- added `babel-macros-plugin`
- environment variable to have cucumber-jest print out the path to the temp directory `CUCUMBER_JEST_SHOW_TEMP_PATH`

### Changes

- refactored glob patterns used for getting variable file paths **[PERFORMANCE](https://github.com/mainfraame/cucumber-jest/issues/10)**
- replaced prototyped methods (filter, find, map, reduce, etc.) with `inline-loops.macro` **[PERFORMANCE](https://github.com/mainfraame/cucumber-jest/issues/10)**

## [0.2.2] - 2021-02-19

### Added
Expand Down
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,10 @@ TAGS="bar, not foo" jest
You can inject values into your feature files using variables.

When variable files are found and injected into a feature file
has variables injected, a temporary feature file with the same name is written to the `node_modules/__temp__` folder.
has variables injected, a temporary feature file with the same name is written to your os's temporary folder;
eg. for mac users, `/var/folders/sb/2wr3vgcd1sxg4tgv1mr8dtq80000gn/T/cucumber-jest`

If you need to figure out the temporary folder path, run the jest with this environment variable `CUCUMBER_JEST_SHOW_TEMP_PATH=true`.

### Use Without ENV

Expand Down Expand Up @@ -648,12 +651,12 @@ Feature: Sign Up - Scenario Outline [Nested]

### Examples

| Type | Feature File | Variable File |
| ---- | ------------ | ------------- |
| Global Variables **Without** Env | [scenarioOutlineNestedGlobal](example/test/features/scenarioOutlineNestedGlobal.feature) | [global.vars.ts](example/test/variables/global.vars.ts) |
| Variables **Without** Env | [scenarioOutline](example/test/features/scenarioOutline.feature) | [scenarioOutline.vars.ts](example/test/variables/scenarioOutline.vars.ts) |
| Global Variables **With** Env | [scenarioOutlineNestedGlobalEnv](example/test/features/scenarioOutlineNestedGlobalEnv.feature) | [global.vars.dev.ts](example/test/variables/global.vars.dev.ts) |
| Variables **With** (dev) | [scenarioOutlineNested](example/test/features/scenarioOutlineNested.feature) | [scenarioOutlineNested.vars.dev.ts](example/test/variables/scenarioOutlineNested.vars.dev.ts) |
| Type | Feature File | Variable File |
| -------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| Global Variables **Without** Env | [scenarioOutlineNestedGlobal](example/test/features/scenarioOutlineNestedGlobal.feature) | [global.vars.ts](example/test/variables/global.vars.ts) |
| Variables **Without** Env | [scenarioOutline](example/test/features/scenarioOutline.feature) | [scenarioOutline.vars.ts](example/test/variables/scenarioOutline.vars.ts) |
| Global Variables **With** Env | [scenarioOutlineNestedGlobalEnv](example/test/features/scenarioOutlineNestedGlobalEnv.feature) | [global.vars.dev.ts](example/test/variables/global.vars.dev.ts) |
| Variables **With** (dev) | [scenarioOutlineNested](example/test/features/scenarioOutlineNested.feature) | [scenarioOutlineNested.vars.dev.ts](example/test/variables/scenarioOutlineNested.vars.dev.ts) |

### Variable File Rules

Expand Down
3 changes: 2 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ module.exports = {
isTSX: true
}
],
'babel-plugin-add-module-exports'
'babel-plugin-add-module-exports',
'babel-plugin-macros'
],
presets: [
[
Expand Down
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"@types/react": "^16.9.32",
"@types/react-dom": "^16.9.6",
"babel-plugin-lodash": "^3.3.4",
"cucumber-jest": "0.2.2",
"cucumber-jest": "0.2.3",
"deep-clean": "^1.0.2",
"jest-date-mock": "^1.0.8",
"msw": "^0.24.1",
Expand Down
14 changes: 5 additions & 9 deletions example/test/variables/global.vars.dev.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
export default {
global: {
email: '[email protected]',
firstName: 'James',
lastName: 'Dean',
password: 'itsASecretShh...'
},
email: '[email protected]',
firstName: 'James',
lastName: 'Dean',
password: 'itsASecretShh...'
email: '[email protected]',
firstName: 'Bill',
lastName: 'Clinton',
password: 'ohMonica'
}
};
14 changes: 5 additions & 9 deletions example/test/variables/global.vars.qa.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
{
"global": {
"email": "[email protected]",
"firstName": "James\\|",
"lastName": "Dean",
"password": "itsASecretShh..."
},
"email": "[email protected]",
"firstName": "James",
"lastName": "Dean",
"password": "itsASecretShh..."
"email": "[email protected]",
"firstName": "George",
"lastName": "Washington",
"password": "iWasTheFirstPresident"
}
}
14 changes: 5 additions & 9 deletions example/test/variables/global.vars.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
export default {
global: {
email: '[email protected]',
firstName: 'James',
lastName: 'Dean',
password: 'itsASecretShh...'
},
email: '[email protected]',
firstName: 'James',
lastName: 'Dean',
password: 'itsASecretShh...'
email: '[email protected]',
firstName: 'Martin',
lastName: 'King',
password: 'justAPersonByTheContentOfTheirCharacter'
}
};
8 changes: 4 additions & 4 deletions example/test/variables/scenarioOutline.vars.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export default {
email: 'james.dean@gmail.com',
firstName: 'James',
lastName: 'Dean',
password: 'itsASecretShh...'
email: 'francis.tarkenton@gmail.com',
firstName: 'Francis',
lastName: 'Tarkenton',
password: 'iOncePlayedForTheVikings'
};
8 changes: 4 additions & 4 deletions example/test/variables/scenarioOutlineNested.vars.dev.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export default {
user: {
email: 'james.dean@gmail.com',
firstName: 'James|',
lastName: 'Dean',
password: 'itsASecretShh...'
email: 'booker.t.washington@gmail.com',
firstName: 'Booker',
lastName: 'Washington',
password: 'mostPeopleKnowMyNameButNotWhatIamFamousFor'
}
};
8 changes: 4 additions & 4 deletions example/test/variables/scenarioOutlineNested.vars.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export default {
user: {
email: 'james.dean@gmail.com',
firstName: 'James|',
lastName: 'Dean',
password: 'itsASecretShh...'
email: 'booker.t.washington@gmail.com',
firstName: 'Booker',
lastName: 'Washington',
password: 'mostPeopleKnowMyNameButNotWhatIamFamousFor'
}
};
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cucumber-jest",
"version": "0.2.2",
"version": "0.2.3",
"description": "a jest transformer for executing cucumber tests in jest",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -43,8 +43,10 @@
"escape-string-regexp": "^4.0.0",
"fast-glob": "~3.2.4",
"flatten-anything": "~2.0.4",
"inline-loops.macro": "^1.2.2",
"jest": ">=26.0.1",
"merge-deep": "^3.0.3",
"mkdirp": "^1.0.4",
"outdent": "^0.8.0",
"react-dom": ">=16.9.0"
},
Expand All @@ -55,10 +57,12 @@
"@babel/preset-env": "^7.12.7",
"@babel/preset-typescript": "^7.12.7",
"@types/jest": "^26.0.16",
"@types/mkdirp": "^1.0.1",
"@types/node": "^14.6.2",
"@types/qs": "^6.9.2",
"@types/react-dom": "^16.9.8",
"babel-plugin-add-module-exports": "^1.0.4",
"babel-plugin-macros": "^3.0.1",
"husky": "^4.3.8",
"import-sort-style-module": "^6.0.0",
"prettier": "^2.2.1",
Expand Down
16 changes: 10 additions & 6 deletions src/configs/env.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os from 'os';
import path from 'path';

const RESERVED_TAGS = ['@debug', '@skip'];
Expand All @@ -9,16 +10,19 @@ const All_TAGS = (process.env.TAGS || '')

const TAGS = All_TAGS.filter((tag) => !RESERVED_TAGS.includes(tag));

export default {
const env = {
ENV_NAME: process.env.ENV || '',
EXCLUDE_TAGS: TAGS.filter((tag) => tag.startsWith('not')).map(
(tag) => tag.split('not ')[1]
),
INCLUDE_TAGS: TAGS.filter((tag) => !tag.startsWith('not')),
TAGS,
TEMP_PATH: path.normalize(
path.resolve(
path.join(process.cwd(), path.join('node_modules', '__tmp__'))
)
)
TEMP_PATH: path.join(os.tmpdir(), 'cucumber-jest'),
SHOW_TEMP_PATH: process.env.CUCUMBER_JEST_SHOW_TEMP_PATH === 'true'
};

if (env.SHOW_TEMP_PATH) {
process.stdout.write(`\ntemporary directory: ${env.TEMP_PATH}\n`);
}

export default env;
8 changes: 5 additions & 3 deletions src/parsers/steps.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import DataTable from '@cucumber/cucumber/lib/models/data_table';
import chalk from 'chalk';
import {filter, find, reduce} from 'inline-loops.macro';
import {outdent} from 'outdent';

import {space} from '../configs/space';
import {isJson} from '../utils/isJson';
import {createDataTable} from './table';

export function parseSteps(steps, definitions) {
return steps.reduce(
return reduce(
steps,
(acc, step) => {
const definition = definitions.find((def) => {
const definition = find(definitions, (def) => {
return def.matchesStepName(step.text);
});

const multiSteps = definitions.filter((def) => {
const multiSteps = filter(definitions, (def) => {
return def.matchesStepName(step.text);
});

Expand Down
80 changes: 43 additions & 37 deletions src/parsers/suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import generateMessages from '@cucumber/gherkin/dist/src/stream/generateMessages
import {messages} from '@cucumber/messages';
import {uuid} from '@cucumber/messages/dist/src/IdGenerator';
import chalk from 'chalk';
import {map, reduce, some} from 'inline-loops.macro';
import outdent from 'outdent';

import env from '../configs/env';
Expand Down Expand Up @@ -56,9 +57,9 @@ export function parseSuite(
${
attachment
? [
`message: ${attachment.text}`,
`column: ${attachment.source.location.column}`,
`line: ${attachment.source.location.line}`,
`message: ${attachment.text}`
`line: ${attachment.source.location.line}`
].join('\n')
: ''
}
Expand All @@ -75,12 +76,13 @@ export function parseSuite(
const hasExcludeTags = env.EXCLUDE_TAGS.length > 0;
const hasTags = env.TAGS.length > 0;

const documentTags = document.tags.map(({name}) => name);
const documentTags = map(document.tags, ({name}) => name);
const documentHasTags =
documentTags.length > 0 && documentTags.some(matchesTags);
const shouldSkipFeature = documentTags.includes('@skip');

const documentContainsSpecsWithTags = specs.some(
const documentContainsSpecsWithTags = some(
specs,
(spec) =>
spec.scenario.tags.length &&
spec.scenario.tags.some(({name}) => matchesTags(name))
Expand All @@ -93,37 +95,41 @@ export function parseSuite(

const documentHasDebugTag = scenarioTags.includes('@debug');

const scenarios = specs.reduce((acc, spec) => {
const tags = spec.scenario.tags.map(({name}) => name);

const examples = parseExampleTable(spec.scenario.examples);

const shouldSkipForDebug =
documentHasDebugTag && !tags.includes('@debug');

const skip =
shouldSkipForDebug ||
tags.includes('@skip') ||
(hasTags && !!tags.length && !tags.some(matchesTags));

return [
...acc,
...(examples.length
? generateExampleTableSteps(examples, spec.scenario).map(
(spec) => ({
...spec,
skip
})
)
: [
{
...spec.scenario,
skip,
steps: spec.scenario.steps
}
])
];
}, []);
const scenarios = reduce(
specs,
(acc, spec) => {
const tags = spec.scenario.tags.map(({name}) => name);

const examples = parseExampleTable(spec.scenario.examples);

const shouldSkipForDebug =
documentHasDebugTag && !tags.includes('@debug');

const skip =
shouldSkipForDebug ||
tags.includes('@skip') ||
(hasTags && !!tags.length && !tags.some(matchesTags));

return [
...acc,
...(examples.length
? generateExampleTableSteps(examples, spec.scenario).map(
(spec) => ({
...spec,
skip
})
)
: [
{
...spec.scenario,
skip,
steps: spec.scenario.steps
}
])
];
},
[]
);

const skipFeature =
shouldSkipFeature ||
Expand All @@ -133,7 +139,7 @@ export function parseSuite(
!hasExcludeTags) ||
scenarios.length === 0;

const suites = scenarios.map((scenario) => ({
const suites = map(scenarios, (scenario) => ({
...scenario,
path: featurePath,
steps: [
Expand All @@ -149,7 +155,7 @@ export function parseSuite(
beforeEach: cucumberSupportCode.beforeTestCaseHookDefinitions,
beforeAll: cucumberSupportCode.beforeTestRunHookDefinitions,
skip: skipFeature,
suites: suites.map((suite) => ({
suites: map(suites, (suite) => ({
...suite,
steps: parseSteps(suite.steps, cucumberSupportCode.stepDefinitions)
}))
Expand Down
Loading

0 comments on commit b66fc41

Please sign in to comment.