Skip to content

Commit

Permalink
feat: adds profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
Ken Howard committed Nov 23, 2018
1 parent 3c36271 commit 40a4f86
Show file tree
Hide file tree
Showing 22 changed files with 605 additions and 46 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ out
node_modules
.vscode-test/
*.vsix
.DS_STORE
5 changes: 4 additions & 1 deletion __mocks__/@octokit/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,7 @@ const mockedGists = {
getStarred: jest.fn(gistsResponse)
};

module.exports = jest.fn(() => ({ gists: mockedGists }));
module.exports = jest.fn(() => ({
authenticate: jest.fn(),
gists: mockedGists
}));
2 changes: 2 additions & 0 deletions __mocks__/vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ module.exports = {
window: {
showErrorMessage: jest.fn(),
showInformationMessage: jest.fn(),
showInputBox: jest.fn(),
showQuickPick: jest.fn(),
showTextDocument: jest.fn()
},
workspace: {
getConfiguration: jest.fn(() => ({ get: jest.fn(), update: jest.fn() })),
openTextDocument: jest.fn()
}
};
25 changes: 16 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,7 @@
"Other"
],
"activationEvents": [
"onCommand:extension.openCodeBlock",
"onCommand:extension.openFavoriteCodeBlock",
"onCommand:extension.createCodeBlock",
"onCommand:extension.openCodeBlockInBrowser",
"onCommand:extension.deleteCodeBlock",
"onCommand:extension.removeFileFromCodeBlock",
"onCommand:extension.addToCodeBlock",
"onCommand:extension.changeCodeBlockDescription",
"onCommand:extension.insertCode"
"*"
],
"main": "./out/extension",
"contributes": {
Expand Down Expand Up @@ -69,6 +61,21 @@
"command": "extension.insertCode",
"title": "GIST: Insert Code Into Current File",
"category": "Gist"
},
{
"command": "extension.toggleProfile",
"title": "GIST: Toggle Profile",
"category": "Gist"
}
],
"keybindings": [
{
"command": "extension.toggleProfile",
"key": "ctrl+alt+="
},
{
"command": "extension.clearProfiles",
"key": "ctrl+alt+0"
}
]
},
Expand Down
44 changes: 39 additions & 5 deletions src/commands/__tests__/gists.commands.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// tslint:disable:no-any no-unsafe-any no-magic-numbers
import { window } from 'vscode';
import { commands, window } from 'vscode';

import { TMP_DIRECTORY_PREFIX } from '../../constants';
import { gists } from '../../gists/gists-service';
Expand All @@ -9,10 +9,12 @@ import { openCodeBlock, updateCodeBlock } from '../gists.commands';
jest.mock('fs');
jest.mock('path');

const executeCommandSpy = jest.spyOn(commands, 'executeCommand');
const editSpy = jest.spyOn(gists, 'update');
const errorSPy = jest.spyOn(logger, 'error');
const errorSpy = jest.spyOn(logger, 'error');
// const getSpy = jest.spyOn(gists, 'get');
const infoSpy = jest.spyOn(logger, 'info');

// const listSpy = jest.spyOn(gists, 'list');
const showQuickPickSpy = jest.spyOn(window, 'showQuickPick');

describe('Gists Commands Tests', () => {
Expand All @@ -26,7 +28,7 @@ describe('Gists Commands Tests', () => {
showQuickPickSpy.mockRejectedValueOnce(false);

await openCodeBlock();
expect(errorSPy.mock.calls.length).toBe(1);
expect(errorSpy.mock.calls.length).toBe(1);
});
test('it opens the quickpick pane', async () => {
expect.assertions(3);
Expand All @@ -41,6 +43,22 @@ describe('Gists Commands Tests', () => {
expect(firstGist.label).toBe('2. gist one');
expect(secondGist.label).toBe('1. gist two');
});
test('it opens a document', async () => {
expect.assertions(1);

showQuickPickSpy.mockResolvedValue({
block: {
id: '123'
},
label: 'foo'
});

await openCodeBlock();

expect(executeCommandSpy).toHaveBeenCalledWith(
'workbench.action.keepEditor'
);
});
});
describe('#updateCodeBlock', () => {
test('should save', async () => {
Expand All @@ -54,7 +72,7 @@ describe('Gists Commands Tests', () => {
expect(editSpy.mock.calls.length).toBe(1);
expect(editSpy.mock.calls[0][0].gist_id).toBe('123456789abcdefg');
expect(editSpy.mock.calls[0][0].files).toStrictEqual({
'test-file-name.md': 'test-file-content'
'test-file-name.md': { content: 'test-file-content' }
});
});
test('should NOT save a non-gist', async () => {
Expand All @@ -67,5 +85,21 @@ describe('Gists Commands Tests', () => {

expect(infoSpy.mock.calls[0][0]).toContain('Not a Gist');
});
test('should handle errors', async () => {
expect.assertions(2);

editSpy.mockRejectedValueOnce(new Error('Not Found'));

const codeBlock = {
fileName: `${TMP_DIRECTORY_PREFIX}_123456789abcdefg_random_string/test-file-name.md`,
getText: jest.fn(() => 'test-file-content')
};

expect(async () => updateCodeBlock(codeBlock)).not.toThrowError();

await updateCodeBlock(codeBlock);

expect(errorSpy).toHaveBeenCalledWith('updateCodeBlock > Not Found');
});
});
});
175 changes: 175 additions & 0 deletions src/commands/__tests__/profile.commands.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// tslint:disable:no-any no-unsafe-any no-magic-numbers
import { commands, window } from 'vscode';

import { logger } from '../../logger';
import { profiles } from '../../profiles';

const debugSpy = jest.spyOn(logger, 'debug');

const executeCommandSpy = jest.spyOn(commands, 'executeCommand');
const showQuickPickSpy = jest.spyOn(window, 'showQuickPick');
const showInformationMessageSpy = jest.spyOn(window, 'showInformationMessage');
const showInputBoxSpy = jest.spyOn(window, 'showInputBox');

import {
clearProfiles,
createProfile,
selectProfile
} from '../profile.commands';

const mockProfile = {
key: '111',
name: 'GHE',
url: 'http://foo.bar.bas'
};

describe('Profile Commands Tests', () => {
afterEach(() => {
jest.resetAllMocks();
});
describe('#clearProfiles', () => {
test('should clear profiles', () => {
expect.assertions(1);

clearProfiles();

expect(executeCommandSpy).toHaveBeenCalledWith(
'extension.updateStatusBar'
);
});
});
describe('#createProfile', () => {
test('should show information message prompt', async () => {
expect.assertions(2);

showInformationMessageSpy.mockResolvedValue({
isCloseAffordance: true,
title: 'GitHub.com (common)'
});

await createProfile();

expect(showInformationMessageSpy).toHaveBeenCalledTimes(1);
expect(showInformationMessageSpy).toHaveBeenCalledWith(
'Which GitHub Platform?',
{ modal: true },
{ title: 'GitHub.com (common)', isCloseAffordance: true },
{ title: 'GitHub Enterprise' }
);
});
test('should gather information from the user', async () => {
expect.assertions(1);

showInformationMessageSpy.mockResolvedValue({
title: 'GitHub Enterprise'
});

showInputBoxSpy.mockResolvedValueOnce('foo');
showInputBoxSpy.mockResolvedValueOnce('bar');
showInputBoxSpy.mockResolvedValueOnce('bat');

await createProfile();

expect(showInputBoxSpy).toHaveBeenCalledTimes(3);
});
test('should log stuff when a user exits without entering "url"', async () => {
expect.assertions(2);

showInformationMessageSpy.mockResolvedValue({
title: 'GitHub Enterprise'
});

showInputBoxSpy.mockResolvedValueOnce(undefined);

await createProfile();

expect(debugSpy).toHaveBeenCalledTimes(1);
expect(debugSpy.mock.calls[0][0]).toContain('"url"');
});
test('should log stuff when a user exits without entering "key"', async () => {
expect.assertions(2);

showInformationMessageSpy.mockResolvedValue({
title: 'GitHub Enterprise'
});

showInputBoxSpy.mockResolvedValueOnce('foo');
showInputBoxSpy.mockResolvedValueOnce(undefined);

await createProfile();

expect(debugSpy).toHaveBeenCalledTimes(1);
expect(debugSpy.mock.calls[0][0]).toContain('"key"');
});
test('should log stuff when a user exits without entering "name"', async () => {
expect.assertions(2);

showInformationMessageSpy.mockResolvedValue({
title: 'GitHub Enterprise'
});

showInputBoxSpy.mockResolvedValueOnce('foo');
showInputBoxSpy.mockResolvedValueOnce('bar');
showInputBoxSpy.mockResolvedValueOnce(undefined);

await createProfile();

expect(debugSpy).toHaveBeenCalledTimes(1);
expect(debugSpy.mock.calls[0][0]).toContain('"name"');
});
});
describe('#selectProfile', () => {
test('should open quick pick to select a profile', async () => {
expect.assertions(1);

const getAllSpy = jest.spyOn(profiles, 'getAll');

getAllSpy.mockReturnValue([mockProfile]);

await selectProfile();

expect(showQuickPickSpy.mock.calls[0].length).toBe(1);
});
test('should open create profile dialog if zero profiles found', async () => {
expect.assertions(3);

const getAllSpy = jest.spyOn(profiles, 'getAll');

await selectProfile();

expect(getAllSpy).toHaveBeenCalledTimes(1);
expect(getAllSpy.mock.results[0].value).toBeUndefined();
expect(executeCommandSpy).toBeCalledWith('extension.createProfile');
});
test('should open create profile dialog if chooses', async () => {
expect.assertions(2);

const getAllSpy = jest.spyOn(profiles, 'getAll');
getAllSpy.mockReturnValue([mockProfile]);

showQuickPickSpy.mockResolvedValue({ label: 'Create New Profile' });

await selectProfile();

expect(getAllSpy).toHaveBeenCalledTimes(1);
expect(executeCommandSpy).toBeCalledWith('extension.createProfile');
});
test('should update gist access key', async () => {
expect.assertions(1);

const getAllSpy = jest.spyOn(profiles, 'getAll');

getAllSpy.mockReturnValue([mockProfile]);

showQuickPickSpy.mockResolvedValueOnce({
profile: mockProfile
});

await selectProfile();

expect(executeCommandSpy).toHaveBeenLastCalledWith(
'extension.updateGistAccessKey'
);
});
});
});
21 changes: 17 additions & 4 deletions src/commands/gists.commands.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { commands, window, workspace } from 'vscode';

import { getGist, getGists, updateGist } from '../gists';
import { configure, getGist, getGists, updateGist } from '../gists';
import { insights } from '../insights';
import { logger } from '../logger';
import { profiles } from '../profiles';
import { extractTextDocumentDetails, filesSync, notify } from '../utils';

const _formatGistsForQuickPick = (gists: Gist[]): QuickPickGist[] =>
Expand Down Expand Up @@ -58,20 +59,26 @@ const openCodeBlock = async (): Promise<void> => {
`Could Not Open Gist ${gistName}`,
`Reason: ${error.message}`
);
} else {
notify.error('Unable To Open Gists', error.message);
}
}
};

const updateCodeBlock = async (doc: GistTextDocument): Promise<void> => {
let file = '';
try {
const { id, filename, content } = extractTextDocumentDetails(doc);
const editor = window.activeTextEditor;
const { id, filename, content, language } = extractTextDocumentDetails(
doc,
editor
);
file = `"${filename}" `;
if (id) {
logger.info(`Saving "${filename}"`);
await updateGist(id, filename, content);
notify.info(`Saved "${filename}"`);
insights.track('save');
insights.track('save', { language });
} else {
logger.info(`"${doc.fileName}" Not a Gist`);
}
Expand All @@ -85,4 +92,10 @@ const updateCodeBlock = async (doc: GistTextDocument): Promise<void> => {
}
};

export { openCodeBlock, updateCodeBlock };
const updateGistAccessKey = (): void => {
const { key, url } = profiles.get();
configure({ key, url });
insights.track('updateGistAccessKey', { url });
};

export { updateGistAccessKey, openCodeBlock, updateCodeBlock };
2 changes: 2 additions & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './gists.commands';
export * from './profile.commands';
export * from './status-bar.commands';

0 comments on commit 40a4f86

Please sign in to comment.