diff --git a/cmds/swagger.js b/cmds/swagger.js index 52a336d44..7506dcc31 100644 --- a/cmds/swagger.js +++ b/cmds/swagger.js @@ -44,6 +44,7 @@ exports.run = async function(opts) { const { spec, version } = opts; let { key, id } = opts; let selectedVersion; + let isUpdate; if (!key && opts.token) { console.warn( @@ -56,9 +57,9 @@ exports.run = async function(opts) { return Promise.reject(new Error('No project API key provided. Please use `--key`.')); } - function callApi(specPath, versionCleaned) { + async function callApi(specPath, versionCleaned) { function success(data) { - const message = !id + const message = !isUpdate ? "You've successfully uploaded a new swagger file to your ReadMe project!" : "You've successfully updated a swagger file on your ReadMe project!"; console.log(` @@ -99,15 +100,46 @@ exports.run = async function(opts) { resolveWithFullResponse: true, }; - // Create - if (!id) { + function createSpec() { return request.post(`${config.host}/api/v1/api-specification`, options).then(success, error); } - // Update - return request - .put(`${config.host}/api/v1/api-specification/${id}`, options) - .then(success, error); + function updateSpec(specId) { + isUpdate = true; + + return request + .put(`${config.host}/api/v1/api-specification/${specId}`, options) + .then(success, error); + } + + /* + Create a new OAS file in Readme: + - Enter flow if user does not pass an id as cli arg + - Check to see if any existing files exist with a specific version + - If none exist, default to creating a new instance of a spec + - If found, prompt user to either create a new spec or update an existing one + */ + + if (!id) { + const apiSettings = await request.get(`${config.host}/api/v1/api-specification`, { + headers: { + 'x-readme-version': versionCleaned, + }, + json: true, + auth: { user: key }, + }); + + if (!apiSettings.length) return createSpec(); + + const { option, specId } = await prompt(promptOpts.createOasPrompt(apiSettings)); + return option === 'create' ? createSpec() : updateSpec(specId); + } + + /* + Update an existing OAS file in Readme: + - Enter flow if user passes an id as cli arg + */ + return updateSpec(id); } async function getSwaggerVersion(versionFlag) { diff --git a/lib/prompts.js b/lib/prompts.js index 05b685e2f..88312c5f8 100644 --- a/lib/prompts.js +++ b/lib/prompts.js @@ -36,6 +36,32 @@ exports.generatePrompts = versionList => [ }, ]; +exports.createOasPrompt = specList => [ + { + type: 'select', + name: 'option', + message: 'Would you like to update an existing OAS file or create a new one?', + choices: [ + { message: 'Update existing', value: 'update' }, + { message: 'Create a new spec', value: 'create' }, + ], + }, + { + type: 'select', + name: 'specId', + message: 'Select your desired file to update', + skip() { + return this.enquirer.answers.option !== 'update'; + }, + choices: specList.map(s => { + return { + message: s.title, + value: s._id, // eslint-disable-line no-underscore-dangle + }; + }), + }, +]; + exports.createVersionPrompt = (versionList, opts, isUpdate) => [ { type: 'select', diff --git a/test/cmds/swagger.test.js b/test/cmds/swagger.test.js index 686e0f866..15024dd31 100644 --- a/test/cmds/swagger.test.js +++ b/test/cmds/swagger.test.js @@ -14,6 +14,8 @@ describe('rdme swagger', () => { afterEach(() => nock.cleanAll()); it('should POST a discovered file if none provided', () => { + promptHandler.createOasPrompt.mockResolvedValue({ option: 'create' }); + const mock = nock(config.host) .get(`/api/v1/version`) .basicAuth({ user: key }) @@ -21,6 +23,9 @@ describe('rdme swagger', () => { .post('/api/v1/version') .basicAuth({ user: key }) .reply(200, { from: '1.0.1', version: '1.0.1' }) + .get(`/api/v1/api-specification`) + .basicAuth({ user: key }) + .reply(200, []) .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) .delayConnection(1000) .basicAuth({ user: key }) @@ -42,6 +47,9 @@ describe('rdme swagger', () => { .get(`/api/v1/version/${version}`) .basicAuth({ user: key }) .reply(200, { version: '1.0.0' }) + .get(`/api/v1/api-specification`) + .basicAuth({ user: key }) + .reply(200, []) .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) .delayConnection(1000) .basicAuth({ user: key }) @@ -54,6 +62,9 @@ describe('rdme swagger', () => { it('should POST to the swagger api if no id provided', () => { const mock = nock(config.host) + .get(`/api/v1/api-specification`) + .basicAuth({ user: key }) + .reply(200, []) .get(`/api/v1/version/${version}`) .basicAuth({ user: key }) .reply(200, { version: '1.0.0' }) @@ -71,6 +82,9 @@ describe('rdme swagger', () => { .get(`/api/v1/version/${version}`) .basicAuth({ user: key }) .reply(200, { version: '1.0.0' }) + .get(`/api/v1/api-specification`) + .basicAuth({ user: key }) + .reply(200, []) .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) .delayConnection(1000) .basicAuth({ user: key }) @@ -98,6 +112,9 @@ describe('rdme swagger', () => { .post('/api/v1/version') .basicAuth({ user: key }) .reply(200, { from: '1.0.1', version: '1.0.1' }) + .get(`/api/v1/api-specification`) + .basicAuth({ user: key }) + .reply(200, []) .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) .basicAuth({ user: key }) .reply(201, { id: 1 }); diff --git a/test/lib/prompts.test.js b/test/lib/prompts.test.js index f6f1cfe30..1d6030364 100644 --- a/test/lib/prompts.test.js +++ b/test/lib/prompts.test.js @@ -11,6 +11,17 @@ const versionlist = [ }, ]; +const specList = [ + { + _id: 'spec1', + title: 'spec1_title', + }, + { + _id: 'spec2', + title: 'spec2_title', + }, +]; + describe('prompt test bed', () => { let enquirer; @@ -53,6 +64,32 @@ describe('prompt test bed', () => { }); }); + describe('createOasPrompt()', () => { + it('should return a create option if selected', async () => { + enquirer.on('prompt', async prompt => { + await prompt.keypress(null, { name: 'down' }); + await prompt.submit(); + }); + const answer = await enquirer.prompt(promptHandler.createOasPrompt([{}])); + + assert.equal(answer.option, 'create'); + assert.equal(answer.specId, ''); + }); + + it('should return specId if user chooses to update file', async () => { + enquirer.on('prompt', async prompt => { + await prompt.keypress(null, { name: 'down' }); + await prompt.keypress(null, { name: 'up' }); + await prompt.submit(); + await prompt.submit(); + }); + const answer = await enquirer.prompt(promptHandler.createOasPrompt(specList)); + + assert.equal(answer.option, 'update'); + assert.equal(answer.specId, 'spec1'); + }); + }); + describe('createVersionPrompt()', () => { it('should allow user to choose a fork if flag is not passed', async () => { const opts = { main: true, beta: true };