Skip to content

Commit

Permalink
Merge pull request #7 from decentraland/feat/use-custom-system-map
Browse files Browse the repository at this point in the history
feat: Use custom system environment variables map
  • Loading branch information
LautaroPetaccio committed Jul 3, 2023
2 parents c0608ac + 072a4b2 commit 59ae18e
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 72 deletions.
215 changes: 150 additions & 65 deletions src/config.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
import { ConfigByEnv, createConfig, IConfig } from './config'
import { Env } from './env'
import { Env, EnvironmentVariables } from './env'

let config: IConfig

const configByEnv: ConfigByEnv = {
[Env.DEVELOPMENT]: {
FOO: 'bar-dev',
},
[Env.STAGING]: {
FOO: 'bar-stg',
},
[Env.PRODUCTION]: {
FOO: 'bar-prod',
},
}
let configByEnv: ConfigByEnv

describe('when using a config', () => {
const { env } = process
Expand All @@ -24,82 +14,177 @@ describe('when using a config', () => {

describe('and getting a variable', () => {
describe('and all the envs are defined', () => {
describe('and the env is Env.DEVELOPMENT', () => {
describe('and the variable exists', () => {
it('should return the value for that variable for the Env.DEVELOPMENT config', () => {
process.env.DCL_DEFAULT_ENV = Env.DEVELOPMENT
config = createConfig(configByEnv)
expect(config.get('FOO')).toBe('bar-dev')
})
})
beforeEach(() => {
configByEnv = {
[Env.DEVELOPMENT]: {
FOO: 'bar-dev',
},
[Env.STAGING]: {
FOO: 'bar-stg',
},
[Env.PRODUCTION]: {
FOO: 'bar-prod',
},
}
})

describe('and the env is Env.STAGING', () => {
describe('and the variable exists', () => {
it('should return the value for that variable for the Env.STAGING config', () => {
process.env.DCL_DEFAULT_ENV = Env.STAGING
config = createConfig(configByEnv)
expect(config.get('FOO')).toBe('bar-stg')
describe.each([Env.DEVELOPMENT, Env.STAGING, Env.PRODUCTION])(
'and the env is %s',
(environment: string) => {
beforeEach(() => {
process.env.DCL_DEFAULT_ENV = environment
})
})
})

describe('and the env is Env.PRODUCTION', () => {
describe('and the variable exists', () => {
it('should return the value for that variable for the Env.PRODUCTION config', () => {
process.env.DCL_DEFAULT_ENV = Env.PRODUCTION
config = createConfig(configByEnv)
expect(config.get('FOO')).toBe('bar-prod')
describe('and the variable exists', () => {
it(`should return the value for that variable for the ${environment} config`, () => {
expect(createConfig(configByEnv).get('FOO')).toBe(
`bar-${environment}`
)
})
})
})
})

describe('and the variable does not exist', () => {
it('should return empty string', () => {
config = createConfig(configByEnv)
expect(config.get('NON_EXISTENT')).toBe('')
})
describe('and the variable does not exist', () => {
let nonExistentVariable: string
let defaultValue: string | undefined

beforeEach(() => {
nonExistentVariable = 'NON_EXISTENT'
})

describe("and there's no default value", () => {
beforeEach(() => {
defaultValue = undefined
})

it('should return empty string', () => {
expect(
createConfig(configByEnv).get(
nonExistentVariable,
defaultValue
)
).toBe('')
})
})

describe('and passing a default value', () => {
it('should return the default value', () => {
config = createConfig(configByEnv)
expect(config.get('NON_EXISTENT', 'someDefaultValue')).toBe(
'someDefaultValue'
)
describe("and there's a default value", () => {
beforeEach(() => {
defaultValue = 'someDefaultValue'
})

it('should return the default value', () => {
expect(
createConfig(configByEnv).get(
nonExistentVariable,
defaultValue
)
).toBe(defaultValue)
})
})
})
})
})
}
)
})

describe('and an env is missing', () => {
const { stg: _, ...configWithMissingEnv } = configByEnv
it('should throw', () => {
beforeEach(() => {
configByEnv = {
[Env.DEVELOPMENT]: {
FOO: 'bar-dev',
},
[Env.PRODUCTION]: {
FOO: 'bar-prod',
},
}
process.env.DCL_DEFAULT_ENV = Env.STAGING
config = createConfig(configWithMissingEnv)
})

it('should throw when retrieving an environment variable', () => {
config = createConfig(configByEnv)
expect(() => config.get('FOO')).toThrow()
})
})
})

describe('and getting the env', () => {
it('should return the env currently used by the config', () => {
process.env.DCL_DEFAULT_ENV = Env.STAGING
config = createConfig(configByEnv)
expect(config.getEnv()).toBe(Env.STAGING)
beforeEach(() => {
configByEnv = {
[Env.DEVELOPMENT]: {
FOO: 'bar-dev',
},
[Env.STAGING]: {
FOO: 'bar-stg',
},
[Env.PRODUCTION]: {
FOO: 'bar-prod',
},
}
})

describe('and the default environment is defined in a custom environment variables map', () => {
let customEnvironment: EnvironmentVariables

beforeEach(() => {
customEnvironment = {
DCL_DEFAULT_ENV: Env.DEVELOPMENT,
}
})

it('should return the env from the custom system environment map', () => {
config = createConfig(configByEnv, {
systemEnvVariables: customEnvironment,
})
expect(config.getEnv()).toBe(Env.DEVELOPMENT)
})
})

describe('and the default environment is defined in the process.env variable', () => {
beforeEach(() => {
process.env.DCL_DEFAULT_ENV = Env.STAGING
})

it('should return the env currently used by the config', () => {
config = createConfig(configByEnv)
expect(config.getEnv()).toBe(Env.STAGING)
})
})
})

describe('and checking if a given env is the current one', () => {
it('should return true if the given env is the current one', () => {
process.env.DCL_DEFAULT_ENV = Env.STAGING
config = createConfig(configByEnv)
expect(config.is(Env.STAGING)).toBe(true)
beforeEach(() => {
configByEnv = {
[Env.DEVELOPMENT]: {
FOO: 'bar-dev',
},
[Env.STAGING]: {
FOO: 'bar-stg',
},
[Env.PRODUCTION]: {
FOO: 'bar-prod',
},
}
})
it('should return false if the given env is not the current one', () => {
process.env.DCL_DEFAULT_ENV = Env.STAGING
config = createConfig(configByEnv)
expect(config.is(Env.DEVELOPMENT)).toBe(false)
expect(config.is(Env.PRODUCTION)).toBe(false)

describe("and it's the current one", () => {
beforeEach(() => {
process.env.DCL_DEFAULT_ENV = Env.STAGING
})

it('should return true', () => {
config = createConfig(configByEnv)
expect(config.is(Env.STAGING)).toBe(true)
})
})

describe("and it's not the current one", () => {
beforeEach(() => {
process.env.DCL_DEFAULT_ENV = Env.STAGING
})

it('should return false', () => {
config = createConfig(configByEnv)
expect(config.is(Env.DEVELOPMENT)).toBe(false)
expect(config.is(Env.PRODUCTION)).toBe(false)
})
})
})
})
6 changes: 3 additions & 3 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Env, getEnv } from './env'
import { Env, EnvironmentVariables, getEnv } from './env'

export interface IConfig {
get: (name: string, defaultValue?: string) => string
Expand All @@ -13,8 +13,8 @@ export type ConfigByEnv = Partial<Record<Env, Record<string, string>>>
* @param configByEnv - A record of variables for each Env
* @returns Config
*/
export function createConfig(configByEnv: ConfigByEnv): IConfig {
const env = getEnv()
export function createConfig(configByEnv: ConfigByEnv, options?: { systemEnvVariables?: EnvironmentVariables }): IConfig {
const env = getEnv(options?.systemEnvVariables)
const config = configByEnv[env]
return {
get: (name, defaultValue = '') => {
Expand Down
10 changes: 8 additions & 2 deletions src/env.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,20 @@ describe('when getting env', () => {
})
})

describe('and env is "dev"', () => {
describe('and the system env variable is "dev"', () => {
it('should return Env.DEVELOPMENT', () => {
mockProcess({ DCL_DEFAULT_ENV: 'dev' })
expect(getEnv()).toBe(Env.DEVELOPMENT)
})
})

describe('and search param is "stg" and env is "dev"', () => {
describe("and there's a custom system environment variable set to dev", () => {
it('should return Env.DEVELOPMENT', () => {
expect(getEnv({ DCL_DEFAULT_ENV: 'dev' })).toBe(Env.DEVELOPMENT)
})
})

describe('and search param is "stg" and the system env variable is "dev"', () => {
it('should return Env.STAGING', () => {
mockLocation({ search: '?env=stg' })
mockProcess({ DCL_DEFAULT_ENV: 'dev' })
Expand Down
6 changes: 4 additions & 2 deletions src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export enum Env {
PRODUCTION = 'prod',
}

export type EnvironmentVariables = Record<string, string | undefined>

/**
* Returns an array with all the possible envs
*/
Expand Down Expand Up @@ -98,7 +100,7 @@ export function getDefaultEnv(
* Returns the Env to be used
* @returns Env
*/
export function getEnv(): Env {
export function getEnv(systemEnvVariables: EnvironmentVariables = process.env): Env {
if (typeof window !== 'undefined') {
const envFromQueryParam = getEnvFromQueryParam(window.location)
if (envFromQueryParam) {
Expand All @@ -111,5 +113,5 @@ export function getEnv(): Env {
}
}

return getDefaultEnv(process.env)
return getDefaultEnv(systemEnvVariables)
}

0 comments on commit 59ae18e

Please sign in to comment.