cucumber-js icon indicating copy to clipboard operation
cucumber-js copied to clipboard

Allow dynamically defining profiles on esm configs

Open notaphplover opened this issue 2 years ago • 10 comments

🤔 What's the problem you're trying to solve?

As developer I would love to dinamycally define profiles on cucumber es module configs.

Actually, the only way to define profiles is exporting the configuration associated to the profile:

cucumberConfig.js

/** @type {import("@cucumber/cucumber/lib/configuration").IConfiguration} */
const profile1 = getConfiguration('profile1');

/** @type {import("@cucumber/cucumber/lib/configuration").IConfiguration} */
const profile2 = getConfiguration('profile2');

/** @type {import("@cucumber/cucumber/lib/configuration").IConfiguration} */
const defaultCucumberConfig = getConfiguration();

export default defaultCucumberConfig;

export { profile1, profile2 };

If I have several dinamycally generated configs, I can't figure out any way to export them in an esm with the current cucumber-js profile configuration.

✨ What's your proposed solution?

There's not a single and best way to achieve this imho. Maybe a default export should be mandatory and it would contain a config or an object with profiles, being default the default one:

cucumberConfig.js

/** @type {import("@cucumber/cucumber/lib/configuration").IConfiguration} */
const profile1 = getConfiguration('profile1');

/** @type {import("@cucumber/cucumber/lib/configuration").IConfiguration} */
const profile2 = getConfiguration('profile2');

/** @type {import("@cucumber/cucumber/lib/configuration").IConfiguration} */
const defaultCucumberConfig = getConfiguration();

const globalConfig = {
  default: defaultCucumberConfig,
  profile1,
  profile2,
}

export default globalConfig;

I'm aware this is a breaking change, cucumber-js could temporaly (until next major) support both syntaxes for a non breaking approach.

⛏ Have you considered any alternatives or workarounds?

Yeah, I could use a common js module but if I'm not mistaken I think esm should not be a second class citizien.

📚 Any additional context?

Consider ECMAScript spec as reference


This text was originally generated from a template, then edited by hand. You can modify the template here.

notaphplover avatar Apr 24 '22 21:04 notaphplover

Sorry, I'm not clear on exactly what the problem is here or how it's specific to ESM.

Could you post a concrete example of something you can do with CommonJS but isn't possible with ESM?

davidjgoss avatar Apr 24 '22 21:04 davidjgoss

Sure ^_^:

CommonJS scenario:

A CommonJS module can be this one:

/** @type {Object.<string, import("@cucumber/cucumber/lib/configuration").IConfiguration>} */
const globalConfig = getGlobalConfig();

module.exports = globalConfig

Keep in mind this globalConfig is an object with string keys (the profile names) and cucumber configs values. In CommonJS I don't need to declare, one by one, the configs I want to export, I can simply set the object to module.exports and cucumber js will accept it.

ESM scenario

There is no way to do this in ESM, I cannot export an object, I can only export an object associated to a key or to the default export:

  • I could export default globalConfig, but cucumber only sees a single invalid default config which is the whole object: an object with string keys (the profile names) and cucumber configs values.

To export the object I have to:

export default globalConfig.default;
export const { profile1, profile2, profile3 } = globalConfig;

But I cannot write a code that exports as many profiles are in globalConfig due to ESM syntax, any export requires the creation of a new variable

notaphplover avatar Apr 25 '22 09:04 notaphplover

Thanks @notaphplover, that makes sense now. I'll follow up here soon.

davidjgoss avatar Apr 26 '22 07:04 davidjgoss

Hi @davidjgoss, may i do something for you at this point? I see the incomplete label on the issue, if you need any additional clarification feel free to reach me :smiley:

notaphplover avatar May 19 '22 15:05 notaphplover

Sorry for the late reply @notaphplover. I'm keen to support this but also to maintain the existing exports pattern as I think it's ergonomic for most users. A bit similar to your idea, my thought would be a special case name like _profiles which you could export and would be treated as a map of profiles.

davidjgoss avatar May 24 '22 07:05 davidjgoss

and/or, your default export could be a function that returns (a promise for) a map of profiles?

davidjgoss avatar May 24 '22 08:05 davidjgoss

Hi @davidjgoss, nothing to say sorry for. Thank you so much for the effort!

I would prefer the default export exporting a function that returns a promise for a map of profiles. _profiles is also a good choice, I don't really have a strong opinion here.

If I had to be picky, thinking in developer experience, I think it's easier to understand a config module which can export an object or a function rather than thinking there's a special _profiles export for doing something which seems to be redundant (of course it's not but I'm thinking in someone who never thought in esm modules nor watched this issue).

I'm happy to contribute to the project following your best practices if you want

notaphplover avatar May 24 '22 13:05 notaphplover

Hello! Any updates on this?

xenbartolokath avatar Nov 29 '23 04:11 xenbartolokath

Hi @xenbartolokath , none so far, if you are interested in this feature I would suggest you to thumbs up the issue :smiley:

notaphplover avatar Nov 29 '23 17:11 notaphplover

Thanks for showing your interest folks. The core team will get to this but I can't promise when.

Meanwhile, if anyone is up for contributing a PR, we'd more than welcome that, and the relevant code is here https://github.com/cucumber/cucumber-js/blob/main/src/configuration/from_file.ts. I think we have a consensus around a default export of an async function that resolves to the profiles.

davidjgoss avatar Dec 12 '23 20:12 davidjgoss

Hey @davidjgoss, sry for the late reply, I just saw it. All right, I'll go for it :smiley:, I think I should be able to deliver a PR in less than a week, depending on the spare time I have

notaphplover avatar Mar 13 '24 23:03 notaphplover