diff --git a/__mocks__/vscode.ts b/__mocks__/vscode.ts index b75f4ad..ba1cf7b 100644 --- a/__mocks__/vscode.ts +++ b/__mocks__/vscode.ts @@ -3,6 +3,7 @@ module.exports = { StatusBarAlignment: { Left: true }, + Uri: { parse: jest.fn((url: string) => url) }, commands: { executeCommand: jest.fn() }, diff --git a/package.json b/package.json index a05a45d..a18bef2 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "category": "GIST" }, { - "command": "extension.openCodeBlockInBrowser", - "title": "Open Block In Browser", + "command": "extension.gist.openInBrowser", + "title": "Open Gist In Browser", "category": "GIST" }, { diff --git a/src/commands/commands.ts b/src/commands/commands.ts index f30a539..db2bf28 100644 --- a/src/commands/commands.ts +++ b/src/commands/commands.ts @@ -10,6 +10,7 @@ const commandInitializers: CommandInitializer[] = [ gists.create, gists.open, gists.openFavorite, + gists.openInBrowser, gists.updateAccessKey, profiles.create, profiles.select, diff --git a/src/commands/extension-commands.ts b/src/commands/extension-commands.ts index 70d8beb..4f71768 100644 --- a/src/commands/extension-commands.ts +++ b/src/commands/extension-commands.ts @@ -2,6 +2,7 @@ enum GistCommands { Create = 'extension.gist.create', Open = 'extension.gist.open', OpenFavorite = 'extension.gist.openFavorite', + OpenInBrowser = 'extension.gist.openInBrowser', UpdateAccessKey = 'extension.gist.updateAccessKey' } diff --git a/src/commands/gists/__tests__/open-in-browser.test.ts b/src/commands/gists/__tests__/open-in-browser.test.ts new file mode 100644 index 0000000..e332be0 --- /dev/null +++ b/src/commands/gists/__tests__/open-in-browser.test.ts @@ -0,0 +1,97 @@ +// tslint:disable:no-any no-magic-numbers +import { commands, window } from 'vscode'; + +import { TMP_DIRECTORY_PREFIX } from '../../../constants'; +import { openInBrowser } from '../open-in-browser'; + +jest.mock('fs'); +jest.mock('path'); + +const getGistsMock = jest.fn(() => [ + { + createdAt: new Date(), + description: 'some markdown file', + fileCount: 1, + files: { 'file-one.md': { content: 'test' } }, + id: '123', + name: 'gist one', + public: true, + updatedAt: new Date(), + url: 'gist-one-url' + }, + { + createdAt: new Date(), + description: 'some markdown file', + fileCount: 1, + files: { 'file-two.md': { content: 'test' } }, + id: '123', + name: 'gist two', + public: true, + updatedAt: new Date(), + url: 'gist-two-url' + } +]); +const getGistMock = jest.fn((id: string) => ({ + createdAt: new Date(), + description: 'some markdown file', + fileCount: 1, + files: { 'file-one.md': { content: 'test' } }, + id, + name: 'test', + public: true, + updatedAt: new Date(), + url: 'test-url' +})); +const utilsMock = jest.genMockFromModule('../../../utils'); +const errorMock = jest.fn(); + +const executeCommandSpy = jest.spyOn(commands, 'executeCommand'); + +describe('open favorite gist', () => { + let openInBrowserFn: CommandFn; + beforeEach(() => { + const gists = { getGists: getGistsMock, getGist: getGistMock }; + const insights = { exception: jest.fn() }; + const logger = { error: errorMock, info: jest.fn() }; + openInBrowserFn = openInBrowser( + { gists, insights, logger } as any, + utilsMock as any + )[1]; + (window).activeTextEditor = undefined; + }); + afterEach(() => { + jest.clearAllMocks(); + }); + test('that a notification is shown when no open documents', async () => { + expect.assertions(1); + + const infoSpy = jest.spyOn(utilsMock.notify, 'info'); + + await openInBrowserFn(); + expect(infoSpy.mock.calls.length).toBe(1); + }); + test('it opens a browser', async () => { + expect.assertions(2); + + (utilsMock.files.extractTextDocumentDetails).mockImplementation( + () => ({ id: '123456789abcdefg', url: 'test-url' }) + ); + + const codeBlock = { + fileName: `${TMP_DIRECTORY_PREFIX}_123456789abcdefg_random_string/test-file-name.md`, + getText: jest.fn(() => 'test-file-content') + }; + + const editor = { + document: codeBlock, + selection: { isEmpty: true } + }; + + (window).activeTextEditor = editor; + + await openInBrowserFn(); + + expect(getGistMock).toHaveBeenCalledWith('123456789abcdefg'); + expect(executeCommandSpy).toHaveBeenCalledWith('vscode.open', 'test-url'); + }); +}); diff --git a/src/commands/gists/index.ts b/src/commands/gists/index.ts index 9300749..642a4ce 100644 --- a/src/commands/gists/index.ts +++ b/src/commands/gists/index.ts @@ -1,4 +1,5 @@ export * from './create'; export * from './open'; export * from './open-favorite'; +export * from './open-in-browser'; export * from './update-access-key'; diff --git a/src/commands/gists/open-in-browser.ts b/src/commands/gists/open-in-browser.ts new file mode 100644 index 0000000..bd189c6 --- /dev/null +++ b/src/commands/gists/open-in-browser.ts @@ -0,0 +1,51 @@ +import { commands, Uri, window } from 'vscode'; + +import { GistCommands } from '../extension-commands'; + +const openInBrowser: CommandInitializer = ( + services: Services, + utils: Utils +): [Command, CommandFn] => { + const { gists, insights, logger } = services; + + const command = GistCommands.OpenInBrowser; + + const commandFn = async (): Promise => { + const gistName = ''; + try { + logger.info(`User Activated ${command}`); + + const editor = window.activeTextEditor; + + if (!editor) { + utils.notify.info('No open documents'); + + return; + } + + const gistId = utils.files.extractTextDocumentDetails(editor.document).id; + + const gist = await gists.getGist(gistId); + + commands.executeCommand('vscode.open', Uri.parse(gist.url)); + + insights.track(command); + } catch (err) { + const error: Error = err as Error; + logger.error(`${command} > ${error && error.message}`); + insights.exception(command, { messsage: error.message }); + if (error && error.message === 'Not Found') { + utils.notify.error( + `Could Not Open Gist ${gistName}`, + `Reason: ${error.message}` + ); + } else { + utils.notify.error('Unable To Open Gists', error.message); + } + } + }; + + return [command, commandFn]; +}; + +export { openInBrowser }; diff --git a/src/extension.ts b/src/extension.ts index eb491eb..41688d2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -55,12 +55,6 @@ export function activate(context: ExtensionContext): void { }); }); - commands.registerCommand( - 'extension.openCodeBlockInBrowser', - (): void => { - // intentionally left blank - } - ); commands.registerCommand( 'extension.deleteCodeBlock', (): void => { diff --git a/src/gists/api.ts b/src/gists/api.ts index d2425f7..f4f6d70 100644 --- a/src/gists/api.ts +++ b/src/gists/api.ts @@ -57,7 +57,8 @@ const formatGist = (gist: GistResponse): Gist => ({ day: 'numeric', month: 'long', year: 'numeric' - }).format(new Date(gist.updated_at)) + }).format(new Date(gist.updated_at)), + url: gist.html_url }); const formatGists = (gistList: GistsResponse): Gist[] => diff --git a/src/typings/global.d.ts b/src/typings/global.d.ts index 3964f3b..4283fcc 100644 --- a/src/typings/global.d.ts +++ b/src/typings/global.d.ts @@ -16,6 +16,7 @@ interface Gist { name: string; public: boolean; updatedAt: string; + url: string; } interface GistTextDocument {