Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Adds utility functions to add envars and update Redwood toml for plugin packages to cli helpers for use in simplifying CLI setup commands #9324

Merged
2 changes: 2 additions & 0 deletions packages/cli-helpers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
"dependencies": {
"@babel/core": "^7.22.20",
"@babel/runtime-corejs3": "7.23.1",
"@iarna/toml": "2.2.5",
"@opentelemetry/api": "1.4.1",
"@redwoodjs/project-config": "6.0.7",
"@redwoodjs/telemetry": "6.0.7",
"chalk": "4.1.2",
"core-js": "3.32.2",
"dotenv": "16.3.1",
"execa": "5.1.1",
"listr2": "6.6.1",
"lodash": "4.17.21",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should add a comment that the existing environment variable value was not changed, but include its new value as a comment 1`] = `
"EXISTING_VAR=value
# CommentedVar=123

# Note: The existing environment variable EXISTING_VAR was not overwritten. Uncomment to use its new value.
# Updated existing variable Comment
# EXISTING_VAR = new_value
"
`;

exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should add a new environment variable when it does not exist 1`] = `
"EXISTING_VAR = value
# CommentedVar = 123

# New Variable Comment
NEW_VAR = new_value
"
`;

exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should add a new environment variable when it does not exist when existing envars have no spacing 1`] = `
"EXISTING_VAR=value
# CommentedVar = 123

# New Variable Comment
NEW_VAR = new_value
"
`;

exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should handle existing environment variables and new value with quoted values by not updating the original value 1`] = `
"EXISTING_VAR = "value"
# CommentedVar = 123

# Note: The existing environment variable EXISTING_VAR was not overwritten. Uncomment to use its new value.
# New Variable Comment
# EXISTING_VAR = new_value
"
`;

exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should handle existing environment variables with quoted values 1`] = `
"EXISTING_VAR = "value"
# CommentedVar = 123
"
`;

exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should handle existing environment variables with quoted values and no spacing 1`] = `
"EXISTING_VAR="value"
# CommentedVar=123
"
`;

exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin adds package but keeps autoInstall false 1`] = `
"[web]
title = "Redwood App"
port = 8_910
apiUrl = "/.redwood/functions"
includeEnvironmentVariables = [ ]

[api]
port = 8_911

[experimental.cli]
autoInstall = false

[[experimental.cli.plugins]]
package = "@example/test-package-when-autoInstall-false"
enabled = true
"
`;

exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin adds when experimental cli has some plugins configured 1`] = `
"[web]
title = "Redwood App"
port = 8_910
apiUrl = "/.redwood/functions"
includeEnvironmentVariables = [ ]

[api]
port = 8_911

[experimental.cli]
autoInstall = true

[[experimental.cli.plugins]]
package = "@existing-example/some-package-when-cli-has-some-packages-configured"

[[experimental.cli.plugins]]
package = "@example/test-package-name"
enabled = true
"
`;

exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin adds when experimental cli is not configured 1`] = `
"[web]
title = "Redwood App"
port = 8_910
apiUrl = "/.redwood/functions"
includeEnvironmentVariables = [ ]

[api]
port = 8_911

[experimental.cli]
autoInstall = true

[[experimental.cli.plugins]]
package = "@example/test-package-when-cli-not-configured"
enabled = true
"
`;

exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin adds when experimental cli is setup but has no plugins configured 1`] = `
"[web]
title = "Redwood App"
port = 8_910
apiUrl = "/.redwood/functions"
includeEnvironmentVariables = [ ]

[api]
port = 8_911

[experimental.cli]
autoInstall = true

[[experimental.cli.plugins]]
package = "@example/test-package-when-no-plugins-configured"
enabled = true
"
`;

exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin does not add duplicate place when experimental cli has that plugin configured 1`] = `
"[web]
title = "Redwood App"
port = 8_910
apiUrl = "/.redwood/functions"
includeEnvironmentVariables = [ ]

[api]
port = 8_911

[experimental.cli]
autoInstall = true

[[experimental.cli.plugins]]
package = "@existing-example/some-package-name-already-exists"

"
`;
214 changes: 214 additions & 0 deletions packages/cli-helpers/src/lib/__tests__/project.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
import fs from 'fs'

import toml from '@iarna/toml'

import { updateTomlConfig, addEnvVar } from '../project' // Replace with the correct path to your module

jest.mock('fs')

const defaultRedwoodToml = {
web: {
title: 'Redwood App',
port: 8910,
apiUrl: '/.redwood/functions',
includeEnvironmentVariables: [],
},
api: {
port: 8911,
},
}

const getRedwoodToml = () => {
return defaultRedwoodToml
}

jest.mock('@redwoodjs/project-config', () => {
return {
getPaths: () => {
return {
generated: {
base: '.redwood',
},
base: '',
}
},
getConfigPath: () => {
return '.redwood.toml'
},
getConfig: () => {
return getRedwoodToml()
},
}
})

describe('addEnvVar', () => {
let envFileContent = ''

describe('addEnvVar adds environment variables as part of a setup task', () => {
beforeEach(() => {
jest.spyOn(fs, 'existsSync').mockImplementation(() => {
return true
})

jest.spyOn(fs, 'readFileSync').mockImplementation(() => {
return envFileContent
})

jest.spyOn(fs, 'writeFileSync').mockImplementation((envPath, envFile) => {
expect(envPath).toContain('.env')
return envFile
})
})

afterEach(() => {
jest.restoreAllMocks()
envFileContent = ''
})

it('should add a new environment variable when it does not exist', () => {
envFileContent = 'EXISTING_VAR = value\n# CommentedVar = 123\n'
const file = addEnvVar('NEW_VAR', 'new_value', 'New Variable Comment')

expect(file).toMatchSnapshot()
})

it('should add a new environment variable when it does not exist when existing envars have no spacing', () => {
envFileContent = 'EXISTING_VAR=value\n# CommentedVar = 123\n'
const file = addEnvVar('NEW_VAR', 'new_value', 'New Variable Comment')

expect(file).toMatchSnapshot()
})

it('should add a comment that the existing environment variable value was not changed, but include its new value as a comment', () => {
envFileContent = 'EXISTING_VAR=value\n# CommentedVar=123\n'
const file = addEnvVar(
'EXISTING_VAR',
'new_value',
'Updated existing variable Comment'
)

expect(file).toMatchSnapshot()
})

it('should handle existing environment variables with quoted values', () => {
envFileContent = `EXISTING_VAR = "value"\n# CommentedVar = 123\n`
const file = addEnvVar('EXISTING_VAR', 'value', 'New Variable Comment')

expect(file).toMatchSnapshot()
})

it('should handle existing environment variables with quoted values and no spacing', () => {
envFileContent = `EXISTING_VAR="value"\n# CommentedVar=123\n`
const file = addEnvVar('EXISTING_VAR', 'value', 'New Variable Comment')

expect(file).toMatchSnapshot()
})

it('should handle existing environment variables and new value with quoted values by not updating the original value', () => {
envFileContent = `EXISTING_VAR = "value"\n# CommentedVar = 123\n`
const file = addEnvVar(
'EXISTING_VAR',
'new_value',
'New Variable Comment'
)

expect(file).toMatchSnapshot()
})
})
})

describe('updateTomlConfig', () => {
describe('updateTomlConfig configures a new CLI plugin', () => {
beforeEach(() => {
jest.spyOn(fs, 'existsSync').mockImplementation(() => {
return true
})

jest.spyOn(fs, 'readFileSync').mockImplementation(() => {
return toml.stringify(defaultRedwoodToml)
})

jest
.spyOn(fs, 'writeFileSync')
.mockImplementation((tomlPath, tomlFile) => {
expect(tomlPath).toContain('redwood.toml')
return tomlFile
})
})

afterEach(() => {
jest.restoreAllMocks()
})

it('adds when experimental cli is not configured', () => {
const file = updateTomlConfig(
'@example/test-package-when-cli-not-configured'
)
expect(file).toMatchSnapshot()
})

it('adds when experimental cli has some plugins configured', () => {
defaultRedwoodToml['experimental'] = {
cli: {
autoInstall: true,
plugins: [
{
package:
'@existing-example/some-package-when-cli-has-some-packages-configured',
},
],
},
}

const file = updateTomlConfig('@example/test-package-name')
expect(file).toMatchSnapshot()
})

it('adds when experimental cli is setup but has no plugins configured', () => {
defaultRedwoodToml['experimental'] = {
cli: {
autoInstall: true,
},
}

const file = updateTomlConfig(
'@example/test-package-when-no-plugins-configured'
)

expect(file).toMatchSnapshot()
})

it('adds package but keeps autoInstall false', () => {
defaultRedwoodToml['experimental'] = {
cli: {
autoInstall: false,
},
}

const file = updateTomlConfig(
'@example/test-package-when-autoInstall-false'
)

expect(file).toMatchSnapshot()
})

it('does not add duplicate place when experimental cli has that plugin configured', () => {
defaultRedwoodToml['experimental'] = {
cli: {
autoInstall: true,
plugins: [
{
package: '@existing-example/some-package-name-already-exists',
},
],
},
}

const file = updateTomlConfig(
'@existing-example/some-package-name-already-exists'
)

expect(file).toMatchSnapshot()
})
})
})
Loading
Loading