Skip to content
This repository was archived by the owner on Dec 18, 2023. It is now read-only.

Commit 0e60be9

Browse files
authored
feat: add envs command and use js config file, liv-6307
feat: add envs command and use js config file
2 parents 7ab51bf + 65f6057 commit 0e60be9

27 files changed

+4348
-104
lines changed

.github/workflows/cli.yml

+13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ name: CLI
66
on:
77
release:
88
types: [created]
9+
push:
910

1011
jobs:
1112
build:
@@ -19,9 +20,21 @@ jobs:
1920
- run: yarn
2021
- run: yarn global add @livestorm/cli
2122

23+
test:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/checkout@v2
27+
- uses: actions/setup-node@v2
28+
with:
29+
node-version: 12
30+
- run: npm install -g yarn
31+
- run: yarn
32+
- run: yarn test
33+
2234
publish-npm:
2335
needs: build
2436
runs-on: ubuntu-latest
37+
if: ${{ github.event_name == 'release' }}
2538
steps:
2639
- uses: actions/checkout@v2
2740
- uses: actions/setup-node@v2

__tests__/cmds/envs/add.spec.ts

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import configStore from 'configstore'
2+
import envs from '../../../src/cmds/envs'
3+
4+
import { fromEnvsAddCmd } from '../../fixtures/configs'
5+
6+
jest.mock('configstore');
7+
8+
const mockedConfigstore = jest.mocked(configStore, true)
9+
10+
describe('Add command', () => {
11+
const envName = 'boron'
12+
const set = mockedConfigstore.mock.instances[0].set as jest.Mock
13+
envs({
14+
_: ['add', envName],
15+
...fromEnvsAddCmd
16+
})
17+
18+
it('should call correctly the config store to set an entry', () => {
19+
expect(set).toHaveBeenCalled()
20+
21+
const [ key, config ] = set.mock.calls[0]
22+
23+
expect(key).toBe(`envs.${envName}`)
24+
25+
const output = {
26+
...fromEnvsAddCmd
27+
}
28+
29+
// @ts-ignore
30+
output.apiToken = fromEnvsAddCmd['api-token']
31+
delete output['api-token']
32+
expect(config).toStrictEqual(output)
33+
});
34+
35+
it('should update correctly an entry in the config store ', () => {
36+
const dataTopdate = {
37+
...fromEnvsAddCmd,
38+
endpoint: 'https://endpoint.fake'
39+
}
40+
envs({
41+
_: ['add', envName],
42+
...dataTopdate
43+
})
44+
45+
const [ key, config ] = set.mock.calls[1]
46+
47+
expect(key).toBe(`envs.${envName}`)
48+
49+
const output = {
50+
...fromEnvsAddCmd,
51+
...dataTopdate
52+
}
53+
54+
// @ts-ignore
55+
output.apiToken = fromEnvsAddCmd['api-token']
56+
delete output['api-token']
57+
expect(config).toStrictEqual(output)
58+
});
59+
})

__tests__/cmds/envs/list.spec.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import configStore from 'configstore'
2+
import envs from '../../../src/cmds/envs'
3+
4+
jest.mock('configstore');
5+
6+
const mockedConfigstore = jest.mocked(configStore, true)
7+
8+
describe('List command', () => {
9+
envs({
10+
_: ['list']
11+
})
12+
13+
it('should call correctly the config store to get all entries of envs', () => {
14+
const get = mockedConfigstore.mock.instances[0].get as jest.Mock
15+
expect(get).toHaveBeenCalled()
16+
17+
const [ key ] = get.mock.calls[0]
18+
expect(key).toBe(`envs`)
19+
});
20+
})

__tests__/cmds/envs/remove.spec.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import configStore from 'configstore'
2+
import envs from '../../../src/cmds/envs'
3+
4+
jest.mock('configstore');
5+
6+
const mockedConfigstore = jest.mocked(configStore, true)
7+
8+
describe('Remove command', () => {
9+
const envName = 'boron'
10+
envs({
11+
_: ['remove', envName]
12+
})
13+
14+
it('should call correctly the config store to delete an entry', () => {
15+
const deleteFn = mockedConfigstore.mock.instances[0].delete as jest.Mock
16+
expect(deleteFn).toHaveBeenCalled()
17+
18+
const [ key ] = deleteFn.mock.calls[0]
19+
expect(key).toBe(`envs.${envName}`)
20+
});
21+
})

__tests__/fixtures/configs.ts

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const baseConfig = {
2+
"name": "baseConfigName",
3+
'apiToken': "baseConfigApiToken",
4+
"permissions": {
5+
"storage": {
6+
"fake-property": {
7+
"write": ["teamMembers"]
8+
}
9+
}
10+
},
11+
"metadata": {
12+
"logo": "https://fakelogo.png",
13+
"translations": {
14+
"title": {
15+
"en": "Fake plugin",
16+
"fr": "Fake plugin",
17+
"es": "Fake plugin"
18+
},
19+
"description": {
20+
"en": "This is a fake plugin",
21+
"fr": "Ceci n'est pas un plugin",
22+
"es": "No es un plugin"
23+
}
24+
}
25+
},
26+
'recorded': true,
27+
}
28+
29+
export default baseConfig
30+
31+
const fromConfigStore = {
32+
'apiToken': "fromConfigStoreApiToken",
33+
'endpoint': 'fromConfigStoreEndpoint',
34+
'recorded': false
35+
}
36+
37+
const fromEnvsAddCmd = {
38+
'api-token': "fromEnvsAddCmdApiToken",
39+
'endpoint': 'fromEnvsAddCmdEndpoint',
40+
'recorded': false
41+
}
42+
43+
const withEnv = {
44+
...baseConfig,
45+
environments: {
46+
fakeEnv: {
47+
'apiToken': "withEnvEndpointApiToken",
48+
'endpoint': 'withEnvEndpoint',
49+
}
50+
}
51+
}
52+
53+
export {
54+
fromConfigStore,
55+
fromEnvsAddCmd,
56+
withEnv
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import os from 'os'
2+
import process from 'process'
3+
import { v4 as uuidv4 } from 'uuid';
4+
import configStore from 'configstore'
5+
import prompts from 'prompts'
6+
7+
import getLivestormConfig from '../../src/helpers/getLivestormConfig'
8+
import livestormDomain from '../../src/helpers/livestormDomain'
9+
10+
import baseConfig, { withEnv, fromConfigStore } from '../fixtures/configs'
11+
12+
enum ConfigFileSources {
13+
LivestormConfig = "livestorm.config.js",
14+
Environments = "environments.json",
15+
}
16+
17+
const fsify = require('fsify')({
18+
cwd: os.tmpdir(),
19+
persistent: false,
20+
force: true
21+
})
22+
23+
let spy = jest.spyOn(process, 'cwd');
24+
let directory
25+
26+
jest.mock('configstore')
27+
jest.mock('prompts')
28+
29+
30+
const writeConfigFile = async (config: any, source = ConfigFileSources.LivestormConfig) => {
31+
const contents = [
32+
{
33+
type: fsify.FILE,
34+
name: source,
35+
contents: source === ConfigFileSources.LivestormConfig ? `module.exports = ${JSON.stringify(config)}` : JSON.stringify(config)
36+
},
37+
]
38+
39+
if (source === ConfigFileSources.Environments) {
40+
contents.push({
41+
type: fsify.FILE,
42+
// @ts-ignore
43+
name: 'package.json',
44+
contents: '{}'
45+
})
46+
}
47+
const structure = [
48+
{
49+
type: fsify.DIRECTORY,
50+
name: directory,
51+
contents,
52+
}
53+
]
54+
55+
await fsify(structure)
56+
}
57+
58+
beforeEach(() => {
59+
directory = uuidv4()
60+
spy.mockReturnValue(os.tmpdir() + '/' + directory);
61+
})
62+
63+
describe('The helper to get the livestorm config', () => {
64+
describe('from the the livestorm.config.js file', () => {
65+
it('should return a simple config by default', async () => {
66+
await writeConfigFile(baseConfig)
67+
const config = await getLivestormConfig()
68+
expect(config).toStrictEqual({
69+
...baseConfig,
70+
endpoint: livestormDomain
71+
})
72+
})
73+
74+
it('should return the conf from the set environment', async () => {
75+
await writeConfigFile(withEnv)
76+
const config = await getLivestormConfig('fakeEnv')
77+
expect(config).toStrictEqual({
78+
...baseConfig,
79+
...withEnv['environments'].fakeEnv
80+
})
81+
})
82+
83+
it('should retrieve the conf from the config store if exists', async () => {
84+
const mockedConfigstore = jest.mocked(configStore, true)
85+
const get = mockedConfigstore.mock.instances[0].get as jest.Mock
86+
87+
get.mockReturnValue(fromConfigStore)
88+
89+
await writeConfigFile(baseConfig)
90+
const config = await getLivestormConfig('fakeEnv')
91+
92+
expect(get).toHaveBeenCalled()
93+
94+
const [ key ] = get.mock.calls[0]
95+
96+
expect(key).toBe(`envs.fakeEnv`)
97+
98+
expect(config).toStrictEqual({
99+
...baseConfig,
100+
...fromConfigStore
101+
})
102+
})
103+
104+
it('should retrieve the conf from the config store if global env is selected', async () => {
105+
const mockedConfigstore = jest.mocked(configStore, true)
106+
const get = mockedConfigstore.mock.instances[0].get as jest.Mock
107+
108+
get.mockReturnValue(fromConfigStore)
109+
110+
const mockedPrompts = jest.mocked(prompts, false)
111+
112+
mockedPrompts.mockReturnValue(Promise.resolve({
113+
selectedEnvConf: 'global'
114+
}))
115+
116+
await writeConfigFile(withEnv)
117+
const config = await getLivestormConfig('fakeEnv')
118+
119+
expect(get).toHaveBeenCalled()
120+
121+
const [ key ] = get.mock.calls[0]
122+
123+
expect(key).toBe(`envs.fakeEnv`)
124+
125+
expect(config).toStrictEqual({
126+
...baseConfig,
127+
...fromConfigStore
128+
})
129+
})
130+
131+
it('should return an error when no config file', async () => {
132+
await expect(getLivestormConfig()).rejects.toBe('The livestorm conf file is missing.');
133+
})
134+
135+
it('should return an error when no name in the config', async () => {
136+
await writeConfigFile({ ...baseConfig, name: null })
137+
await expect(getLivestormConfig()).rejects.toBe('The name is missing.');
138+
})
139+
140+
it('should return an error when no API Token in the config', async () => {
141+
await writeConfigFile({ ...baseConfig, apiToken: null })
142+
await expect(getLivestormConfig()).rejects.toBe('The API Token is missing.');
143+
})
144+
})
145+
146+
describe('from the the environments.json file', () => {
147+
it('should return a simple config by default', async () => {
148+
await writeConfigFile({
149+
development: baseConfig
150+
}, ConfigFileSources.Environments)
151+
const config = await getLivestormConfig()
152+
expect(config).toStrictEqual({
153+
...baseConfig,
154+
endpoint: livestormDomain
155+
})
156+
})
157+
158+
it('should return the env config if set', async () => {
159+
await writeConfigFile({
160+
production: baseConfig
161+
}, ConfigFileSources.Environments)
162+
const config = await getLivestormConfig('production')
163+
expect(config).toStrictEqual({
164+
...baseConfig,
165+
endpoint: livestormDomain
166+
})
167+
})
168+
})
169+
170+
describe('with 2 conf files', () => {
171+
it('should return the conf from livestorm.config.js', async () => {
172+
await writeConfigFile({ ...baseConfig, name: 'fromLivestormConfJs' })
173+
await writeConfigFile({
174+
development: {
175+
...baseConfig,
176+
name: 'fromEnvironmentsJson'
177+
}
178+
}, ConfigFileSources.Environments)
179+
const config = await getLivestormConfig()
180+
expect(config.name).toBe('fromLivestormConfJs')
181+
})
182+
})
183+
})

babel.config.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
presets: [
3+
['@babel/preset-env', {targets: {node: 'current'}}],
4+
'@babel/preset-typescript',
5+
],
6+
};

0 commit comments

Comments
 (0)