Search code examples
rolluprollupjs

how to use rollup to parse cucumber feature files and backing step definition files


I have the following rollup plugin that will include .feature files

export const cucumberRollupPlugin: PluginImpl<CucumberOptions> = pluginOptions => {
  let options: CucumberOptions = {
    ...{
      include: '**/*.feature',
      cwd: process.cwd(),
    },
    ...pluginOptions,
  };

  let filter = createFilter(options);

  let plugin: Plugin = {
    name: 'bigtest-cucumber',
    async transform(code, id) {
      if (!filter(id)) {
        return;
      }

      let parser = new GherkinParser({ code, uri: id, rootDir: options.cwd });

      let result = await parser.parse();

      let esm = dataToEsm(result, { namedExports: false });

      // TODO: add sourcemap support
      let transformResult: TransformResult = { code: esm };

      return transformResult;
    },
  };

  return plugin;
};

The problem I have is that to make the feature files work, there are step definition files that actually contain the functionality. So a feature file might look like this

Feature: Visit career guide page in career.guru99.com
Scenario: Visit career.guru99.com
Given: I browse to career.guru99.com

And a step definition file might look like this:

import { Given, When, Then from 'cucumber';
import assert from 'assert';
import{ driver } from '../support/web_driver';

Given(/^browse to web site "([^"]*)"$/, async function(url) {
    return driver.get(url);
});

The problem I have with rollup is that there are no import statements for either the step definition files. The way cucumber-js works is that these files are found at runtime.

I think I need to generate an index.js that looks like this to cover the step definitions.

import from './step_definition_1';
import from './step_definition_2';
import from './step_definition_3';

Where would this fit in the rollup pipeline to generate this file so it can get pulled into the rollup pipeline.


Solution

  • You can use this.emitFile to manually process the .feature files and include them in the output. Call this.emitFile for each .feature file in the buildStart hook (each emitted file will get processed through the transform hook you wrote).

    Here's an example that uses the globby package (which expands a glob to an array of file paths) to get the file path of each .feature file to pass to this.emitFile:

    import globby from 'globby'
    
    export const cucumberRollupPlugin: PluginImpl<CucumberOptions> = pluginOptions => {
      let options: CucumberOptions = {
        include: '**/*.feature',
        cwd: process.cwd(),
        ...pluginOptions,
      };
    
      let filter = createFilter(options);
    
      let plugin: Plugin = {
        name: 'bigtest-cucumber',
        async buildStart({ include, cwd }) {
          const featureFilePaths = await globby(include, { cwd });
    
          for (const featureFilePath of featureFilePaths) {
            this.emitFile({
              type: 'chunk',
              id: featureFilePath
            });
          }
        },
        async transform(code, id) {
          if (!filter(id)) {
            return;
          }
    
          let parser = new GherkinParser({ code, uri: id, rootDir: options.cwd });
    
          let result = await parser.parse();
    
          let esm = dataToEsm(result, { namedExports: false });
    
          // TODO: add sourcemap support
          let transformResult: TransformResult = { code: esm };
    
          return transformResult;
        },
      };
    
      return plugin;
    };
    

    Let me know if you have any questions!