Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
8 changes: 7 additions & 1 deletion .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,11 @@ out/**/*.map
src/**
.gitignore
tsconfig.json
tsconfig.prod.json
vsc-extension-quickstart.md
tslint.json
tslint.json
jest.config.js
coverage/**
bin/**
.github/**
__mocks__/**
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';
Loading