{"id":15552276,"url":"https://github.com/bahmutov/cypress-ld-control","last_synced_at":"2025-09-28T19:30:40.308Z","repository":{"id":40411724,"uuid":"465783972","full_name":"bahmutov/cypress-ld-control","owner":"bahmutov","description":"Set LaunchDarkly feature flags from Cypress tests","archived":false,"fork":false,"pushed_at":"2024-08-13T16:57:01.000Z","size":175,"stargazers_count":17,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-12-27T20:41:24.773Z","etag":null,"topics":["cypress-plugin","launchdarkly"],"latest_commit_sha":null,"homepage":"https://glebbahmutov.com/blog/cypress-and-launchdarkly/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bahmutov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-03-03T15:50:32.000Z","updated_at":"2024-08-13T16:55:46.000Z","dependencies_parsed_at":"2023-01-17T18:45:55.690Z","dependency_job_id":null,"html_url":"https://github.com/bahmutov/cypress-ld-control","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcypress-ld-control","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcypress-ld-control/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcypress-ld-control/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcypress-ld-control/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bahmutov","download_url":"https://codeload.github.com/bahmutov/cypress-ld-control/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234552257,"owners_count":18851240,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cypress-plugin","launchdarkly"],"created_at":"2024-10-02T14:14:30.036Z","updated_at":"2025-09-28T19:30:40.302Z","avatar_url":"https://github.com/bahmutov.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cypress-ld-control ![cypress version](https://img.shields.io/badge/cypress-15.2.0-brightgreen) [![ci](https://github.com/bahmutov/cypress-ld-control/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/bahmutov/cypress-ld-control/actions/workflows/ci.yml)\n\n\u003e Set LaunchDarkly feature flags from Cypress tests\n\n- 📝 Read the blog post [Control LaunchDarkly From Cypress Tests](https://glebbahmutov.com/blog/cypress-and-launchdarkly/).\n- 📝 Read the blog post [Diff Feature Flags Before Running Tests](https://glebbahmutov.com/blog/diff-feature-flags-before-testing/).\n\n## Install\n\nAdd this plugin as a dev dependency\n\n```bash\n# install using NPM\n$ npm i -D cypress-ld-control\n# install using Yarn\n$ yarn add -D cypress-ld-control\n```\n\nMost common use case: using this plugin from Cypress\n\nAdd the plugin to your Node-side plugins or config file\n\n```js\n// cypress.config.js\n// https://github.com/bahmutov/cypress-ld-control\nconst { initCypress } = require('cypress-ld-control')\n...\ne2e: {\n  setupNodeEvents(on, config) {\n    initCypress(on, config)\n    // IMPORTANT: return the updated config object\n    return config\n  },\n}\n```\n\nIf you want custom `cy` commands to fetch or control the feature flags, include the plugin's commands file from your support file or from your spec file:\n\n```js\n// your support or spec file\n// https://github.com/bahmutov/cypress-ld-control\nimport 'cypress-ld-control/commands'\n```\n\n## API\n\n### Commands\n\nFrom the spec or browser support file you can import the `cypress-ld-control/commands` module to add utility commands\n\n#### isLaunchDarklyControlInitialized\n\nStatic, chained off `Cypress`\n\n```js\nif (Cypress.isLaunchDarklyControlInitialized()) {\n  // we can control the LaunchDarkly flags\n}\n```\n\n### getFeatureFlag\n\n```js\ncy.getFeatureFlag(featureFlagKey, projectKey?).then(flag =\u003e ...)\n```\n\n### setFeatureFlagForUser\n\n```js\ncy.setFeatureFlagForUser(featureFlagKey, userId, variationIndex)\n```\n\n### removeUserTarget\n\n```js\ncy.removeUserTarget(featureFlagKey, userId)\n```\n\n## Plugin Node API\n\nThis plugin provides the following functions\n\n### getFeatureFlags\n\nReturns all feature flags. Warning: could be a lot of flags!\n\n```js\nconst flags = await ldApi.getFeatureFlags()\n// flags is an array of objects\n```\n\n### getFeatureFlag\n\nReturns a large object with everything there is two know about the feature flag in a particular environment\n\n```js\nconst flag = ldApi.getFeatureFlag('my-feature-flag')\n```\n\n### setFeatureFlagForUser\n\n**Important:** the feature flag must have \"Targeting: on\" for user-level targeting to work.\n\n```js\nawait ldApi.setFeatureFlagForUser({\n  featureFlagKey: 'my-flag-key',\n  userId: 'string user id',\n  variationIndex: 1, // must be index to one of the variations\n})\n```\n\n### removeTarget\n\nRemoves the specified target object\n\n```js\nawait ldApi.removeTarget({\n  featureFlagKey: 'my-flag-key',\n  targetIndex: 0,\n})\n```\n\n### removeUserTarget\n\nRemoves the given user from any variation targeting lists for the given feature\n\n```js\nawait ldApi.removeUserTarget({\n  featureFlagKey: 'my-flag-key',\n  userId: 'user string id',\n})\n```\n\n## Use without Cypress\n\nYou can use this plugin by itself to control LaunchDarkly flags\n\n```js\n// https://github.com/bahmutov/cypress-ld-control\nconst { initLaunchDarklyApiClient } = require('cypress-ld-control')\nconst ldApi = initLaunchDarklyApiClient({\n  projectKey: process.env.LAUNCH_DARKLY_PROJECT_KEY,\n  authToken: process.env.LAUNCH_DARKLY_AUTH_TOKEN,\n  environment: 'test', // the key of the environment to use\n})\nconst flag = await ldApi.getFeatureFlag('my-flag-key')\nawait ldApi.setFeatureFlagForUser({\n  featureFlagKey: 'my-flag-key',\n  userId: '1234567',\n  variationIndex: 0, // index of the variant to use\n})\n```\n\nSee [demo/index.js](./demo/index.js)\n\n## CLI\n\nYou can list all project's flags for specific environment\n\n```shell\n# needs LAUNCH_DARKLY_AUTH_TOKEN environment variable\n$ LAUNCH_DARKLY_AUTH_TOKEN=... npx list-ld-flags --project demo-project --environment test\n# same as\n$ LAUNCH_DARKLY_AUTH_TOKEN=... LAUNCH_DARKLY_PROJECT_KEY=demo-project npx list-ld-flags -e test\n```\n\nOnly the most important properties of each feature flag for the given environment are listed.\n\nYou can save the feature flags JSON in a file and then check if any flags have changed values\n\n```shell\n$ LAUNCH_DARKLY_AUTH_TOKEN=... LAUNCH_DARKLY_PROJECT_KEY=demo-project npx list-ld-flags -e test --diff \u003cfilename.json\u003e\n```\n\n## Use from Cypress\n\nAdd the plugin to your Cypress plugins file by grabbing an object with tasks.\n\n### initCypress\n\nFrom your Cypress config file (v10+) or from your plugins file, call the `initCypress` function.\n\n```js\n// cypress.config.js\nconst { initCypress } = require('cypress-ld-control')\nsetupNodeEvents(on, config) {\n  initCypress(on, config)\n  // IMPORTANT: return the updated config object\n  return config\n}\n```\n\nReads the environment variables `LAUNCH_DARKLY_PROJECT_KEY` and `LAUNCH_DARKLY_AUTH_TOKEN` to initialize the LD client. You can pass the LD environment name via `LAUNCH_DARKLY_ENVIRONMENT`, otherwise it assumes the LD environment name is \"test\".\n\n### initCypressMultipleProjects\n\nSometimes you might have several LaunchDarkly projects. You can control each one, and all you need is `LAUNCH_DARKLY_AUTH_TOKEN` environment variable.\n\n```js\n// cypress.config.js\nconst { initCypressMultipleProjects } = require('cypress-ld-control')\nsetupNodeEvents(on, config) {\n  // list all the LD projects you want to use\n  const projects = [\n    {\n      projectKey: 'demo-project',\n      environment: 'test',\n    },\n    {\n      projectKey: 'api-project',\n      environment: 'test',\n    },\n  ]\n\n  initCypressMultipleProjects(projects, on, config)\n\n  // IMPORTANT: return the updated config object\n  return config\n}\n```\n\nWhen calling the `cy` custom commands from [commands.js](./commands.js) pass the project key, for example\n\n```js\ncy.getFeatureFlag(featureFlagKey, projectKey)\n```\n\n#### Project names\n\nSince some projects might have \"default\" as the project key, you can give them your own \"name\"\n\n```js\n// list all the LD projects you want to use\nconst projects = [\n  {\n    name: 'web-flags',\n    projectKey: 'default',\n    environment: 'test',\n  },\n  {\n    projectKey: 'api-project',\n    environment: 'test',\n  },\n]\n\ninitCypressMultipleProjects(projects, on, config)\n```\n\nIn the situation above you can get the flag for first project using either of the two keys:\n\n```js\ncy.getFeatureFlag('my-flag', 'default')\ncy.getFeatureFlag('my-flag', 'web-flags')\n```\n\n### Explicit registration (old)\n\n**Tip:** you might want to check if the environment variables `and` are set and only initialize the tasks in that case.\n\n```js\n// cypress/plugins/index.js\nconst { initLaunchDarklyApiTasks } = require('cypress-ld-control')\nmodule.exports = (on, config) =\u003e {\n  const tasks = {\n    // add your other Cypress tasks if any\n  }\n\n  // https://github.com/bahmutov/cypress-ld-control\n  if (\n    process.env.LAUNCH_DARKLY_PROJECT_KEY \u0026\u0026\n    process.env.LAUNCH_DARKLY_AUTH_TOKEN\n  ) {\n    const ldApiTasks = initLaunchDarklyApiTasks({\n      projectKey: process.env.LAUNCH_DARKLY_PROJECT_KEY,\n      authToken: process.env.LAUNCH_DARKLY_AUTH_TOKEN,\n      environment: 'test', // the key of the environment to use\n    })\n    // copy all LaunchDarkly methods as individual tasks\n    Object.assign(tasks, ldApiTasks)\n  } else {\n    console.log('Skipping cypress-ld-control plugin')\n  }\n\n  // register all tasks with Cypress\n  on('task', tasks)\n\n  // IMPORTANT: return the updated config object\n  return config\n}\n```\n\nEach method from the API (see above) has a matching task prefixed with `cypress-ld-control:` string. For example, to see a particular flag from your spec call:\n\n```js\n// in your Cypress spec file\n// let's find everything about a feature flag\ncy.task('cypress-ld-control:getFeatureFlag', 'my-flag-key').then(flag =\u003e {...})\n// let's set the feature variation for a user\ncy.task('cypress-ld-control:setFeatureFlagForUser', {\n  featureFlagKey: 'my-flag-key',\n  userId: 'string user id',\n  variationIndex: 1 // must be index to one of the variations\n})\n```\n\n## Examples\n\n- application [bahmutov/cypress-ld-control-example](https://github.com/bahmutov/cypress-ld-control-example)\n\n## Types\n\nIn [src/index.d.ts](./src/index.d.ts) file and [src/globals.d.ts](./src/globals.d.ts)\n\n## Small print\n\nAuthor: Gleb Bahmutov \u0026lt;gleb.bahmutov@gmail.com\u0026gt; \u0026copy; 2022\n\n- [@bahmutov](https://twitter.com/bahmutov)\n- [glebbahmutov.com](https://glebbahmutov.com)\n- [blog](https://glebbahmutov.com/blog)\n- [videos](https://www.youtube.com/glebbahmutov)\n- [presentations](https://slides.com/bahmutov)\n- [cypress.tips](https://cypress.tips)\n- [Cypress Tips \u0026 Tricks Newsletter](https://cypresstips.substack.com/)\n\nLicense: MIT - do anything with the code, but don't blame me if it does not work.\n\nSupport: if you find any problems with this module, email / tweet /\n[open issue](https://github.com/bahmutov/cypress-ld-control/issues) on Github\n\n## MIT License\n\nCopyright (c) 2022 Gleb Bahmutov \u0026lt;gleb.bahmutov@gmail.com\u0026gt;\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahmutov%2Fcypress-ld-control","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbahmutov%2Fcypress-ld-control","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahmutov%2Fcypress-ld-control/lists"}