Skip to content

Commit

Permalink
cypress-dotenv v3.x
Browse files Browse the repository at this point in the history
- Upgrading Cypress and DotEnv to the latest version
- Dropping support for anything below Node v18
- Minimum version of Cypress is now v10
- Fixing #32
  • Loading branch information
morficus authored Dec 30, 2024
2 parents 7d3cb9f + 8652bf4 commit 27841ee
Show file tree
Hide file tree
Showing 14 changed files with 4,019 additions and 2,460 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ NON_CYPRESS_TEST_VAR=goodbye
CYPRESS_BASE_URL=http://google.com
CYPRESS_ENV=testing
CYPRESS_I_AM_NUMBER=100
CYPRESS_I_AM_BOOLEAN=true
CYPRESS_I_AM_BOOLEAN=true
CYPRESS_I_AM_A_NUMBER_WITH_LEADING_ZERO=0100
26 changes: 5 additions & 21 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,9 @@ Please fill out this section with a description of your changes and your approac

_fill me out 📝_

## How to test/verify these changes
## Verification Checklist

<!--
Replace the sample steps below with steps on how a reviewer of this PR can test your changes. This should include things such as (if applicable):
* Do you need to use a specific account to log in?
* Is there a particular patient profile that should be used?
-->

1. Clone this branch and run: `npm run cypress`
1. Next, do thing 1
1. Now do thing 2
1. Notice that XYZ has changed


## Screenshots and/or video

<!--
If relevant, make sure to include relevant video or before/after screenshots that demonstrate the changes.
If no visuals are required, then please fill out this section with "N/A"
-->

_fill me out 📸_
- [ ] Provided a good description of the changes introduced with this PR.
- [ ] Written adequate unit tests (if necessary)
- [ ] Updated the README (if necessary)
- [ ] Make sure things still work with v10 and up of Cypress
20 changes: 20 additions & 0 deletions .github/workflows/pr-quality-checks.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Run a number of quality checks ever time a PR is opened
name: Pull Request Quality Checks

permissions:
contents: read
pull-requests: read
on:
workflow_dispatch:
inputs:
Expand Down Expand Up @@ -60,3 +63,20 @@ jobs:
env:
CI: true
NODE_ENV: test

integration-testing:
name: Integration testing
runs-on: ubuntu-latest
needs: setup
steps:
# restore dependencies that were installed in the `setup` job
- name: Restore dependencies
uses: actions/cache@v3
with:
path: |
./*
~/.npm
key: ${{ github.sha }}

- name: Cypress Run
uses: cypress-io/github-action@v6
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20
18
46 changes: 21 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Cypress dotenv

Cypress plugin that enables compatability with [dotenv](https://www.npmjs.com/package/dotenv).
Cypress plugin that enables compatibility with [dotenv](https://www.npmjs.com/package/dotenv).

> [!NOTE]
> If you need support for Cypress v9 or below, please use [v2.x of this plugin](https://github.com/morficus/cypress-dotenv/tree/v2.0.2)

[![Build Status](https://travis-ci.org/morficus/cypress-dotenv.svg?branch=master)](https://travis-ci.org/morficus/cypress-dotenv)
[![Maintainability](https://api.codeclimate.com/v1/badges/0d189dae8e924ada81ad/maintainability)](https://codeclimate.com/github/morficus/cypress-dotenv/maintainability)
Expand Down Expand Up @@ -35,41 +39,33 @@ yarn add --dev dotenv cypress-dotenv

## Configure

Cypress (< 10.0.0)

Since this is a plugin, you will need to modify your file `cypress/plugins/index.js` to look something like this:

```javascript
const dotenvPlugin = require('cypress-dotenv');
module.exports = (on, config) => {
config = dotenvPlugin(config)
return config
}
```
Version 3.x of this plugin only supports Cypress v10+. For instructions on how to set up this plugin with older versions of Cypress, please refer to the [v2.x README](https://github.com/morficus/cypress-dotenv/tree/v2.0.2?tab=readme-ov-file#configure)

Cypress (>= 10.0.0)

According to [Migration Guide](https://docs.cypress.io/guides/references/migration-guide#Plugins-File-Removed):
The setupNodeEvents() config option is functionally equivalent to the function exported from the plugins file
Since this is a plugin, you will need to modify your `cypress.config.js` to look something like this

```javascript
```typescript
import { defineConfig } from 'cypress'
import dotenvPlugin from 'cypress-dotenv'

export default defineConfig({
e2e: {
...
setupNodeEvents(on, config) {
return dotenvPlugin(config)
},
e2e: {
...
setupNodeEvents(on, config) {
const updatedConfig = dotenvPlugin(config, null, true)
// continue loading other plugins
return updatedConfig
},
},
...
})
```

## Options
This plugin takes three paramaters. The first parameter (which is mandatory) is the Cypress config object.

The second is an optional [dotenv](https://www.npmjs.com/package/dotenv#config) config object.

The third is an optional [all] boolean parameter, which is set to false by default. If set to true, it returns all available environmental variables, not limited to those prefixed with CYPRESS_.
## Options
This plugin takes three parameters:

1. The first parameter (which is mandatory) is the Cypress config object.
1. The second is an optional [dotenv](https://www.npmjs.com/package/dotenv#config) config object.
1. The third (called `all`) is an optional boolean parameter, which is set to false by default. If set to true, it returns all available environmental variables, not limited to those prefixed with CYPRESS_.
16 changes: 16 additions & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const { defineConfig } = require('cypress')
const dotenvPlugin = require('./index')

module.exports = defineConfig({
video: false,
e2e: {
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
const updatedConfig = dotenvPlugin(config, null, true)
// continue loading other plugins

return updatedConfig
}
}
})
3 changes: 0 additions & 3 deletions cypress.json

This file was deleted.

File renamed without changes.
25 changes: 0 additions & 25 deletions cypress/plugins/index.js

This file was deleted.

File renamed without changes.
47 changes: 36 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@ const camelcase = require('camelcase')
const clonedeep = require('lodash.clonedeep')
const pkgName = '[cypress-dotenv]'

/**
* Checks if something that was parsed as a number should be a string instead.
* Specifically for cases where a number has a leading zero
* See: https://github.com/morficus/cypress-dotenv/issues/32
*/
function checkIfTrulyNumber({ parsedValue, rawValue }) {
let correctValue = parsedValue

if (typeof parsedValue === 'number' && rawValue.startsWith('0')) {
// if env var has a leading zero, then it must be a string and not a number
correctValue = rawValue
}

return correctValue
}

/**
* Cypress dotenv plugin
*
Expand All @@ -19,36 +35,45 @@ module.exports = (cypressConfig, dotEnvConfig, all = false) => {
const cypressPrefix = 'CYPRESS_'

// load the content of the .env file, then parse each variable to the correct type (string, number, boolean, etc.)
let envVars = require('dotenv').config(dotEnvConfig)
const rawEnvVars = require('dotenv').config(dotEnvConfig).parsed

// if no env vars were parsed, then there is nothing to do here (most likely an empty or non-existing .env file)
if (envVars.parsed === undefined) {
// if no env vars were found, then there is nothing to do here (most likely an empty or non-existing .env file)
if (rawEnvVars === undefined || rawEnvVars === null || Object.keys(rawEnvVars).length === 0) {
return cypressConfig
}

const dotenvParseVariables = require('dotenv-parse-variables')
envVars = dotenvParseVariables(envVars.parsed)
const parsedEnvVars = dotenvParseVariables(rawEnvVars)

const enhancedConfig = clonedeep(cypressConfig)
enhancedConfig.env = enhancedConfig.env || {}

// get the name of all env vars that relate to cypress
const cypressEnvVarKeys = all
? Object.keys(envVars)
: Object.keys(envVars).filter((envName) => envName.startsWith(cypressPrefix))
? Object.keys(parsedEnvVars)
: Object.keys(parsedEnvVars).filter((envName) => envName.startsWith(cypressPrefix))

cypressEnvVarKeys.forEach((originalName) => {
// remove the CYPRESS_ prefix from the env var name
const pattern = new RegExp(`^${cypressPrefix}`, 'g')
const cleanName = originalName.replace(pattern, '')

// convert the env var name from snake_case to camelCase
const camelCaseName = camelcase(cleanName)
const parsedEnvar = envVars[originalName]
const processEnvVar = process.env[originalName]
const envVar = typeof parsedEnvar === 'string' ? processEnvVar : parsedEnvar

enhancedConfig.env[cleanName] = envVar
const parsedValue = parsedEnvVars[originalName]
const rawValue = process.env[originalName]

let effectiveValue = typeof parsedValue === 'string' ? rawValue : parsedValue

if (typeof effectiveValue === 'number') {
effectiveValue = checkIfTrulyNumber({ parsedValue: effectiveValue, rawValue })
}

enhancedConfig.env[cleanName] = effectiveValue

if (enhancedConfig.hasOwnProperty(camelCaseName) && camelCaseName !== 'env') {
enhancedConfig[camelCaseName] = envVar
enhancedConfig[camelCaseName] = effectiveValue
}
})

Expand Down
13 changes: 10 additions & 3 deletions index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('Cypress dotenv plugin', () => {
expect(enhancedConfig.env).toEqual({})
})

it('Should only add CYPRESS_ vars to the config', () => {
it('Should only add CYPRESS_ vars to the config by default', () => {
const enhancedConfig = plugin(cypressConfigExample)

expect(enhancedConfig.env.TEST_VAR).toBeDefined()
Expand Down Expand Up @@ -72,6 +72,11 @@ describe('Cypress dotenv plugin', () => {
expect(enhancedConfig.env.I_AM_NUMBER).toEqual(100)
})

it('Should parse things that are numbers with leading zeros, as a string', () => {
const enhancedConfig = plugin(cypressConfigExample)
expect(enhancedConfig.env.I_AM_A_NUMBER_WITH_LEADING_ZERO).toEqual('0100')
})

it('Should parse things that are booleans, as booleans', () => {
const enhancedConfig = plugin(cypressConfigExample)
expect(enhancedConfig.env.I_AM_BOOLEAN).toEqual(true)
Expand All @@ -96,7 +101,8 @@ describe('Cypress dotenv plugin', () => {
ENV: 'testing',
I_AM_BOOLEAN: true,
I_AM_NUMBER: 100,
TEST_VAR: 'hello'
TEST_VAR: 'hello',
I_AM_A_NUMBER_WITH_LEADING_ZERO: '0100'
}
const enhancedConfig = plugin({})

Expand All @@ -123,7 +129,8 @@ describe('Cypress dotenv plugin', () => {
I_AM_BOOLEAN: true,
I_AM_NUMBER: 100,
NON_CYPRESS_TEST_VAR: 'goodbye',
TEST_VAR: 'hello'
TEST_VAR: 'hello',
I_AM_A_NUMBER_WITH_LEADING_ZERO: '0100'
})
})
})
Expand Down
Loading

0 comments on commit 27841ee

Please sign in to comment.