github-file-spec.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. const fs = require('fs-plus')
  2. const path = require('path')
  3. const temp = require('temp').track()
  4. const GitHubFile = require('../lib/github-file')
  5. const {it, fit, ffit, beforeEach, afterEach} = require('./async-spec-helpers') // eslint-disable-line no-unused-vars
  6. describe('GitHubFile', function () {
  7. let githubFile
  8. let editor
  9. describe('commands', () => {
  10. let workingDirPath
  11. function fixturePath (fixtureName) {
  12. return path.join(__dirname, 'fixtures', `${fixtureName}.git`)
  13. }
  14. function setupWorkingDir (fixtureName) {
  15. workingDirPath = temp.mkdirSync('open-on-github-working-dir-')
  16. fs.copySync(fixturePath(fixtureName), path.join(workingDirPath, '.git'))
  17. let subdirectoryPath = path.join(workingDirPath, 'some-dir')
  18. fs.makeTreeSync(subdirectoryPath)
  19. let filePath = path.join(subdirectoryPath, 'some-file.md')
  20. fs.writeFileSync(filePath, 'some file content')
  21. }
  22. async function setupGithubFile (filePath = 'some-dir/some-file.md') {
  23. atom.project.setPaths([workingDirPath])
  24. editor = await atom.workspace.open(filePath)
  25. githubFile = GitHubFile.fromPath(editor.getPath())
  26. return githubFile
  27. }
  28. describe('open', () => {
  29. describe('when the file is openable on GitHub.com', () => {
  30. let fixtureName = 'github-remote'
  31. beforeEach(async () => {
  32. setupWorkingDir(fixtureName)
  33. await setupGithubFile()
  34. })
  35. it('opens the GitHub.com blob URL for the file', () => {
  36. spyOn(githubFile, 'openURLInBrowser')
  37. githubFile.open()
  38. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blob/master/some-dir/some-file.md')
  39. })
  40. describe('when text is selected', () => {
  41. it('opens the GitHub.com blob URL for the file with the selection range in the hash', () => {
  42. atom.config.set('open-on-github.includeLineNumbersInUrls', true)
  43. spyOn(githubFile, 'openURLInBrowser')
  44. githubFile.open([[0, 0], [1, 1]])
  45. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blob/master/some-dir/some-file.md#L1-L2')
  46. })
  47. })
  48. describe("when the file has a '#' in its name", () => {
  49. it('opens the GitHub.com blob URL for the file', async () => {
  50. editor = await atom.workspace.open('a/b#/test#hash.md')
  51. githubFile = GitHubFile.fromPath(editor.getPath())
  52. spyOn(githubFile, 'openURLInBrowser')
  53. githubFile.open()
  54. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blob/master/a/b%23/test%23hash.md')
  55. })
  56. })
  57. })
  58. describe('when the file is part of a GitHub wiki', () => {
  59. let fixtureName = 'github-remote-wiki'
  60. beforeEach(async () => {
  61. setupWorkingDir(fixtureName)
  62. await setupGithubFile()
  63. })
  64. it('opens the GitHub.com wiki URL for the file', () => {
  65. spyOn(githubFile, 'openURLInBrowser')
  66. githubFile.open()
  67. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/wiki/some-file')
  68. })
  69. })
  70. describe('when the file is part of a GitHub gist', () => {
  71. let fixtureName = 'github-remote-gist'
  72. beforeEach(async () => {
  73. setupWorkingDir(fixtureName)
  74. await setupGithubFile('some-file.md')
  75. })
  76. it('opens the gist.github.com URL for the file', () => {
  77. spyOn(githubFile, 'openURLInBrowser')
  78. githubFile.open()
  79. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://gist.github.com/s0m3ha5h#file-some-file-md')
  80. })
  81. })
  82. describe("when the branch has a '/' in its name", () => {
  83. let fixtureName = 'branch-with-slash-in-name'
  84. beforeEach(async () => {
  85. setupWorkingDir(fixtureName)
  86. await setupGithubFile()
  87. })
  88. it('opens the GitHub.com blob URL for the file', () => {
  89. spyOn(githubFile, 'openURLInBrowser')
  90. githubFile.open()
  91. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blob/foo/bar/some-dir/some-file.md')
  92. })
  93. })
  94. describe("when the branch has a '#' in its name", () => {
  95. let fixtureName = 'branch-with-hash-in-name'
  96. beforeEach(async () => {
  97. setupWorkingDir(fixtureName)
  98. await setupGithubFile()
  99. })
  100. it('opens the GitHub.com blob URL for the file', () => {
  101. spyOn(githubFile, 'openURLInBrowser')
  102. githubFile.open()
  103. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blob/a%23b%23c/some-dir/some-file.md')
  104. })
  105. })
  106. describe("when the remote has a '/' in its name", () => {
  107. let fixtureName = 'remote-with-slash-in-name'
  108. beforeEach(async () => {
  109. setupWorkingDir(fixtureName)
  110. await setupGithubFile()
  111. })
  112. it('opens the GitHub.com blob URL for the file', () => {
  113. spyOn(githubFile, 'openURLInBrowser')
  114. githubFile.open()
  115. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blob/baz/some-dir/some-file.md')
  116. })
  117. })
  118. describe('when the local branch is not tracked', () => {
  119. let fixtureName = 'non-tracked-branch'
  120. beforeEach(async () => {
  121. setupWorkingDir(fixtureName)
  122. await setupGithubFile()
  123. })
  124. it('opens the GitHub.com blob URL for the file on the master branch', () => {
  125. spyOn(githubFile, 'openURLInBrowser')
  126. githubFile.open()
  127. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blob/master/some-dir/some-file.md')
  128. })
  129. })
  130. describe('when there is no remote', () => {
  131. let fixtureName = 'no-remote'
  132. beforeEach(async () => {
  133. setupWorkingDir(fixtureName)
  134. await setupGithubFile()
  135. })
  136. it('shows a warning', () => {
  137. spyOn(atom.notifications, 'addWarning')
  138. githubFile.open()
  139. expect(atom.notifications.addWarning).toHaveBeenCalledWith('No URL defined for remote: null')
  140. })
  141. })
  142. describe("when the root directory doesn't have a git repo", () => {
  143. beforeEach(async () => {
  144. workingDirPath = temp.mkdirSync('open-on-github-working-dir')
  145. await setupGithubFile()
  146. })
  147. it('does nothing', () => {
  148. spyOn(atom.notifications, 'addWarning')
  149. githubFile.open()
  150. expect(atom.notifications.addWarning).toHaveBeenCalled()
  151. expect(atom.notifications.addWarning.mostRecentCall.args[0]).toContain('No repository found')
  152. })
  153. })
  154. describe('when the remote repo is not hosted on github.com', () => {
  155. let fixtureName = 'github-enterprise-remote'
  156. beforeEach(async () => {
  157. setupWorkingDir(fixtureName)
  158. githubFile = await setupGithubFile()
  159. })
  160. it('opens a GitHub enterprise style blob URL for the file', () => {
  161. spyOn(githubFile, 'openURLInBrowser')
  162. githubFile.open()
  163. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://git.enterprize.me/some-user/some-repo/blob/master/some-dir/some-file.md')
  164. })
  165. })
  166. describe('when the git config is set', () => {
  167. let fixtureName = 'git-config'
  168. beforeEach(async () => {
  169. setupWorkingDir(fixtureName)
  170. githubFile = await setupGithubFile()
  171. })
  172. it('opens a URL that is specified by the git config', () => {
  173. spyOn(githubFile, 'openURLInBrowser')
  174. githubFile.open()
  175. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/foo/bar/blob/some-branch/some-dir/some-file.md')
  176. })
  177. })
  178. })
  179. describe('openOnMaster', () => {
  180. describe('when the file is openable on GitHub.com', () => {
  181. let fixtureName = 'non-tracked-branch'
  182. beforeEach(async () => {
  183. setupWorkingDir(fixtureName)
  184. await setupGithubFile()
  185. })
  186. it('opens the GitHub.com blob URL for the file', () => {
  187. spyOn(githubFile, 'openURLInBrowser')
  188. githubFile.openOnMaster()
  189. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blob/master/some-dir/some-file.md')
  190. })
  191. })
  192. describe('when the file is part of a GitHub wiki', () => {
  193. let fixtureName = 'github-remote-wiki'
  194. beforeEach(async () => {
  195. setupWorkingDir(fixtureName)
  196. await setupGithubFile()
  197. })
  198. it('opens the GitHub.com wiki URL for the file and behaves exactly like open', () => {
  199. spyOn(githubFile, 'openURLInBrowser')
  200. githubFile.openOnMaster()
  201. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/wiki/some-file')
  202. })
  203. })
  204. describe('when the file is part of a GitHub gist', () => {
  205. let fixtureName = 'github-remote-gist'
  206. beforeEach(async () => {
  207. setupWorkingDir(fixtureName)
  208. await setupGithubFile('some-file.md')
  209. })
  210. it('opens the gist.github.com URL for the file and behaves exactly like open', () => {
  211. spyOn(githubFile, 'openURLInBrowser')
  212. githubFile.openOnMaster()
  213. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://gist.github.com/s0m3ha5h#file-some-file-md')
  214. })
  215. })
  216. })
  217. describe('blame', () => {
  218. describe('when the file is openable on GitHub.com', () => {
  219. let fixtureName = 'github-remote'
  220. beforeEach(async () => {
  221. setupWorkingDir(fixtureName)
  222. await setupGithubFile()
  223. })
  224. it('opens the GitHub.com blame URL for the file', () => {
  225. spyOn(githubFile, 'openURLInBrowser')
  226. githubFile.blame()
  227. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blame/master/some-dir/some-file.md')
  228. })
  229. describe('when text is selected', () => {
  230. it('opens the GitHub.com blame URL for the file with the selection range in the hash', () => {
  231. atom.config.set('open-on-github.includeLineNumbersInUrls', true)
  232. spyOn(githubFile, 'openURLInBrowser')
  233. githubFile.blame([[0, 0], [1, 1]])
  234. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blame/master/some-dir/some-file.md#L1-L2')
  235. })
  236. })
  237. })
  238. describe('when the local branch is not tracked', () => {
  239. let fixtureName = 'non-tracked-branch'
  240. beforeEach(async () => {
  241. setupWorkingDir(fixtureName)
  242. await setupGithubFile()
  243. })
  244. it('opens the GitHub.com blame URL for the file on the master branch', () => {
  245. spyOn(githubFile, 'openURLInBrowser')
  246. githubFile.blame()
  247. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/blame/master/some-dir/some-file.md')
  248. })
  249. })
  250. describe('when the file is part of a GitHub wiki', () => {
  251. let fixtureName = 'github-remote-wiki'
  252. beforeEach(async () => {
  253. setupWorkingDir(fixtureName)
  254. await setupGithubFile()
  255. })
  256. it('shows a warning and does not attempt to open a URL', () => {
  257. spyOn(githubFile, 'openURLInBrowser')
  258. spyOn(atom.notifications, 'addWarning')
  259. githubFile.blame()
  260. expect(atom.notifications.addWarning).toHaveBeenCalledWith('Blames do not exist for wikis')
  261. expect(githubFile.openURLInBrowser).not.toHaveBeenCalled()
  262. })
  263. })
  264. describe('when the file is part of a GitHub wiki', () => {
  265. let fixtureName = 'github-remote-gist'
  266. beforeEach(async () => {
  267. setupWorkingDir(fixtureName)
  268. await setupGithubFile()
  269. })
  270. it('shows a warning and does not attempt to open a URL', () => {
  271. spyOn(githubFile, 'openURLInBrowser')
  272. spyOn(atom.notifications, 'addWarning')
  273. githubFile.blame()
  274. expect(atom.notifications.addWarning).toHaveBeenCalledWith('Blames do not exist for gists')
  275. expect(githubFile.openURLInBrowser).not.toHaveBeenCalled()
  276. })
  277. })
  278. })
  279. describe('branchCompare', () => {
  280. describe('when the file is openable on GitHub.com', () => {
  281. let fixtureName = 'github-remote'
  282. beforeEach(async () => {
  283. setupWorkingDir(fixtureName)
  284. await setupGithubFile()
  285. })
  286. it('opens the GitHub.com branch compare URL for the file', () => {
  287. spyOn(githubFile, 'openURLInBrowser')
  288. githubFile.openBranchCompare()
  289. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/compare/master')
  290. })
  291. })
  292. describe('when the file is part of a GitHub wiki', () => {
  293. let fixtureName = 'github-remote-wiki'
  294. beforeEach(async () => {
  295. setupWorkingDir(fixtureName)
  296. await setupGithubFile()
  297. })
  298. it('shows a warning and does not attempt to open a URL', () => {
  299. spyOn(githubFile, 'openURLInBrowser')
  300. spyOn(atom.notifications, 'addWarning')
  301. githubFile.openBranchCompare()
  302. expect(atom.notifications.addWarning).toHaveBeenCalledWith('Branches do not exist for wikis')
  303. expect(githubFile.openURLInBrowser).not.toHaveBeenCalled()
  304. })
  305. })
  306. describe('when the file is part of a GitHub wiki', () => {
  307. let fixtureName = 'github-remote-gist'
  308. beforeEach(async () => {
  309. setupWorkingDir(fixtureName)
  310. await setupGithubFile()
  311. })
  312. it('shows a warning and does not attempt to open a URL', () => {
  313. spyOn(githubFile, 'openURLInBrowser')
  314. spyOn(atom.notifications, 'addWarning')
  315. githubFile.openBranchCompare()
  316. expect(atom.notifications.addWarning).toHaveBeenCalledWith('Branches do not exist for gists')
  317. expect(githubFile.openURLInBrowser).not.toHaveBeenCalled()
  318. })
  319. })
  320. })
  321. describe('history', () => {
  322. describe('when the file is openable on GitHub.com', () => {
  323. let fixtureName = 'github-remote'
  324. beforeEach(async () => {
  325. setupWorkingDir(fixtureName)
  326. await setupGithubFile()
  327. })
  328. it('opens the GitHub.com history URL for the file', () => {
  329. spyOn(githubFile, 'openURLInBrowser')
  330. githubFile.history()
  331. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/commits/master/some-dir/some-file.md')
  332. })
  333. })
  334. describe('when the local branch is not tracked', () => {
  335. let fixtureName = 'non-tracked-branch'
  336. beforeEach(async () => {
  337. setupWorkingDir(fixtureName)
  338. await setupGithubFile()
  339. })
  340. it('opens the GitHub.com history URL for the file on the master branch', () => {
  341. spyOn(githubFile, 'openURLInBrowser')
  342. githubFile.history()
  343. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/commits/master/some-dir/some-file.md')
  344. })
  345. })
  346. describe('when the file is part of a GitHub wiki', () => {
  347. let fixtureName = 'github-remote-wiki'
  348. beforeEach(async () => {
  349. setupWorkingDir(fixtureName)
  350. await setupGithubFile()
  351. })
  352. it('opens the GitHub.com wiki history URL for the file', () => {
  353. spyOn(githubFile, 'openURLInBrowser')
  354. githubFile.history()
  355. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/wiki/some-file/_history')
  356. })
  357. })
  358. describe('when the file is part of a GitHub gist', () => {
  359. let fixtureName = 'github-remote-gist'
  360. beforeEach(async () => {
  361. setupWorkingDir(fixtureName)
  362. await setupGithubFile('some-file.md')
  363. })
  364. it('opens the gist.github.com history URL for the gist', () => {
  365. spyOn(githubFile, 'openURLInBrowser')
  366. githubFile.history()
  367. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://gist.github.com/s0m3ha5h/revisions')
  368. })
  369. })
  370. })
  371. describe('copyURL', () => {
  372. describe('when the file is openable on GitHub.com', () => {
  373. let fixtureName = 'github-remote'
  374. beforeEach(async () => {
  375. setupWorkingDir(fixtureName)
  376. atom.config.set('open-on-github.includeLineNumbersInUrls', true)
  377. await setupGithubFile()
  378. })
  379. describe('when text is selected', () => {
  380. it('copies the URL to the clipboard with the selection range in the hash', () => {
  381. githubFile.copyURL([[0, 0], [1, 1]])
  382. expect(atom.clipboard.read()).toBe('https://github.com/some-user/some-repo/blob/80b7897ceb6bd7531708509b50afeab36a4b73fd/some-dir/some-file.md#L1-L2')
  383. })
  384. })
  385. describe('when no text is selected', () => {
  386. it('copies the URL to the clipboard with the cursor location in the hash', () => {
  387. githubFile.copyURL([[2, 1], [2, 1]])
  388. expect(atom.clipboard.read()).toBe('https://github.com/some-user/some-repo/blob/80b7897ceb6bd7531708509b50afeab36a4b73fd/some-dir/some-file.md#L3')
  389. })
  390. })
  391. })
  392. describe('when the file is part of a GitHub wiki', () => {
  393. let fixtureName = 'github-remote-wiki'
  394. beforeEach(async () => {
  395. setupWorkingDir(fixtureName)
  396. atom.config.set('open-on-github.includeLineNumbersInUrls', true)
  397. await setupGithubFile()
  398. })
  399. it('copies the GitHub.com wiki URL to the clipboard and ignores any selection ranges', () => {
  400. githubFile.copyURL([[0, 0], [1, 1]])
  401. expect(atom.clipboard.read()).toBe('https://github.com/some-user/some-repo/wiki/some-file/80b7897ceb6bd7531708509b50afeab36a4b73fd')
  402. })
  403. })
  404. describe('when the file is part of a GitHub gist', () => {
  405. let fixtureName = 'github-remote-gist'
  406. beforeEach(async () => {
  407. setupWorkingDir(fixtureName)
  408. atom.config.set('open-on-github.includeLineNumbersInUrls', true)
  409. await setupGithubFile('some-file.md')
  410. })
  411. describe('when text is selected', () => {
  412. it('copies the gist.github.com URL with the selection range with the selection range appended', () => {
  413. githubFile.copyURL([[0, 0], [1, 1]])
  414. expect(atom.clipboard.read()).toBe('https://gist.github.com/s0m3ha5h/80b7897ceb6bd7531708509b50afeab36a4b73fd#file-some-file-md-L1-L2')
  415. })
  416. })
  417. describe('when no text is selected', () => {
  418. it('copies the gist.github.com URL with the selection range with the cursor location appended', () => {
  419. githubFile.copyURL([[2, 1], [2, 1]])
  420. expect(atom.clipboard.read()).toBe('https://gist.github.com/s0m3ha5h/80b7897ceb6bd7531708509b50afeab36a4b73fd#file-some-file-md-L3')
  421. })
  422. })
  423. })
  424. })
  425. describe('openRepository', () => {
  426. describe('when the file is openable on GitHub.com', () => {
  427. let fixtureName = 'github-remote'
  428. beforeEach(async () => {
  429. setupWorkingDir(fixtureName)
  430. await setupGithubFile()
  431. })
  432. it('opens the GitHub.com repository URL', () => {
  433. spyOn(githubFile, 'openURLInBrowser')
  434. githubFile.openRepository()
  435. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo')
  436. })
  437. })
  438. describe('when the file is part of a GitHub wiki', () => {
  439. let fixtureName = 'github-remote-wiki'
  440. beforeEach(async () => {
  441. setupWorkingDir(fixtureName)
  442. await setupGithubFile()
  443. })
  444. it('opens the GitHub.com wiki history URL for the file', () => {
  445. spyOn(githubFile, 'openURLInBrowser')
  446. githubFile.openRepository()
  447. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/wiki')
  448. })
  449. })
  450. describe('when the file is part of a GitHub gist', () => {
  451. let fixtureName = 'github-remote-gist'
  452. beforeEach(async () => {
  453. setupWorkingDir(fixtureName)
  454. await setupGithubFile('some-file.md')
  455. })
  456. it('opens the gist.github.com repository URL', () => {
  457. spyOn(githubFile, 'openURLInBrowser')
  458. githubFile.openRepository()
  459. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://gist.github.com/s0m3ha5h')
  460. })
  461. })
  462. })
  463. describe('openIssues', () => {
  464. describe('when the file is openable on GitHub.com', () => {
  465. let fixtureName = 'github-remote'
  466. beforeEach(async () => {
  467. setupWorkingDir(fixtureName)
  468. await setupGithubFile()
  469. })
  470. it('opens the GitHub.com issues URL', () => {
  471. spyOn(githubFile, 'openURLInBrowser')
  472. githubFile.openIssues()
  473. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/issues')
  474. })
  475. })
  476. describe('when the file is part of a GitHub wiki', () => {
  477. let fixtureName = 'github-remote-wiki'
  478. beforeEach(async () => {
  479. setupWorkingDir(fixtureName)
  480. await setupGithubFile()
  481. })
  482. it('shows a warning and does not attempt to open a URL', () => {
  483. spyOn(githubFile, 'openURLInBrowser')
  484. spyOn(atom.notifications, 'addWarning')
  485. githubFile.openIssues()
  486. expect(atom.notifications.addWarning).toHaveBeenCalledWith('Issues do not exist for wikis')
  487. expect(githubFile.openURLInBrowser).not.toHaveBeenCalled()
  488. })
  489. })
  490. describe('when the file is part of a GitHub wiki', () => {
  491. let fixtureName = 'github-remote-gist'
  492. beforeEach(async () => {
  493. setupWorkingDir(fixtureName)
  494. await setupGithubFile()
  495. })
  496. it('shows a warning and does not attempt to open a URL', () => {
  497. spyOn(githubFile, 'openURLInBrowser')
  498. spyOn(atom.notifications, 'addWarning')
  499. githubFile.openIssues()
  500. expect(atom.notifications.addWarning).toHaveBeenCalledWith('Issues do not exist for gists')
  501. expect(githubFile.openURLInBrowser).not.toHaveBeenCalled()
  502. })
  503. })
  504. })
  505. describe('openPullRequests', () => {
  506. describe('when the file is openable on GitHub.com', () => {
  507. let fixtureName = 'github-remote'
  508. beforeEach(async () => {
  509. setupWorkingDir(fixtureName)
  510. await setupGithubFile()
  511. })
  512. it('opens the GitHub.com pull requests URL', () => {
  513. spyOn(githubFile, 'openURLInBrowser')
  514. githubFile.openPullRequests()
  515. expect(githubFile.openURLInBrowser).toHaveBeenCalledWith('https://github.com/some-user/some-repo/pulls')
  516. })
  517. })
  518. describe('when the file is part of a GitHub wiki', () => {
  519. let fixtureName = 'github-remote-wiki'
  520. beforeEach(async () => {
  521. setupWorkingDir(fixtureName)
  522. await setupGithubFile()
  523. })
  524. it('shows a warning and does not attempt to open a URL', () => {
  525. spyOn(githubFile, 'openURLInBrowser')
  526. spyOn(atom.notifications, 'addWarning')
  527. githubFile.openPullRequests()
  528. expect(atom.notifications.addWarning).toHaveBeenCalledWith('Pull requests do not exist for wikis')
  529. expect(githubFile.openURLInBrowser).not.toHaveBeenCalled()
  530. })
  531. })
  532. describe('when the file is part of a GitHub wiki', () => {
  533. let fixtureName = 'github-remote-gist'
  534. beforeEach(async () => {
  535. setupWorkingDir(fixtureName)
  536. await setupGithubFile()
  537. })
  538. it('shows a warning and does not attempt to open a URL', () => {
  539. spyOn(githubFile, 'openURLInBrowser')
  540. spyOn(atom.notifications, 'addWarning')
  541. githubFile.openPullRequests()
  542. expect(atom.notifications.addWarning).toHaveBeenCalledWith('Pull requests do not exist for gists')
  543. expect(githubFile.openURLInBrowser).not.toHaveBeenCalled()
  544. })
  545. })
  546. })
  547. })
  548. describe('githubRepoURL', () => {
  549. beforeEach(() => {
  550. githubFile = new GitHubFile()
  551. })
  552. it('returns the GitHub.com URL for an HTTPS remote URL', () => {
  553. githubFile.gitURL = () => 'https://github.com/foo/bar.git'
  554. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar')
  555. })
  556. it('will only strip a single .git suffix', () => {
  557. githubFile.gitURL = () => 'https://github.com/foo/bar.git.git'
  558. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar.git')
  559. githubFile.gitURL = () => 'https://github.com/foo/bar.git.other.git'
  560. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar.git.other')
  561. })
  562. it('returns the GitHub.com URL for an HTTP remote URL', () => {
  563. githubFile.gitURL = () => 'http://github.com/foo/bar.git'
  564. expect(githubFile.githubRepoURL()).toBe('http://github.com/foo/bar')
  565. })
  566. it('returns the GitHub.com URL for an SSH remote URL', () => {
  567. githubFile.gitURL = () => 'git@github.com:foo/bar.git'
  568. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar')
  569. })
  570. it('returns a GitHub enterprise URL for a non-Github.com remote URL', () => {
  571. githubFile.gitURL = () => 'https://git.enterprize.me/foo/bar.git'
  572. expect(githubFile.githubRepoURL()).toBe('https://git.enterprize.me/foo/bar')
  573. githubFile.gitURL = () => 'git@git.enterprize.me:foo/bar.git'
  574. expect(githubFile.githubRepoURL()).toBe('https://git.enterprize.me/foo/bar')
  575. })
  576. it('returns the GitHub.com URL for a git:// URL', () => {
  577. githubFile.gitURL = () => 'git://github.com/foo/bar.git'
  578. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar')
  579. })
  580. it('returns the GitHub.com URL for a user@github.com URL', () => {
  581. githubFile.gitURL = () => 'https://user@github.com/foo/bar.git'
  582. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar')
  583. })
  584. it('returns the GitHub.com URL for a ssh:// URL', () => {
  585. githubFile.gitURL = () => 'ssh://git@github.com/foo/bar.git'
  586. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar')
  587. })
  588. it('returns undefined for Bitbucket URLs', () => {
  589. githubFile.gitURL = () => 'https://bitbucket.org/somebody/repo.git'
  590. expect(githubFile.githubRepoURL()).toBeUndefined()
  591. githubFile.gitURL = () => 'https://bitbucket.org/somebody/repo'
  592. expect(githubFile.githubRepoURL()).toBeUndefined()
  593. githubFile.gitURL = () => 'git@bitbucket.org:somebody/repo.git'
  594. expect(githubFile.githubRepoURL()).toBeUndefined()
  595. githubFile.gitURL = () => 'git@bitbucket.org:somebody/repo'
  596. expect(githubFile.githubRepoURL()).toBeUndefined()
  597. })
  598. it('removes leading and trailing slashes', () => {
  599. githubFile.gitURL = () => 'https://github.com/foo/bar/'
  600. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar')
  601. githubFile.gitURL = () => 'https://github.com/foo/bar//////'
  602. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar')
  603. githubFile.gitURL = () => 'git@github.com:/foo/bar.git'
  604. expect(githubFile.githubRepoURL()).toBe('https://github.com/foo/bar')
  605. })
  606. })
  607. describe('when determining whether a repository is a Gist repository or not', () => {
  608. it('does not throw when the repository URL is a Bitbucket URL (regression)', () => {
  609. githubFile.gitURL = () => 'https://bitbucket.org/somebody/repo.git'
  610. expect(githubFile.isGistURL()).toBe(false)
  611. })
  612. })
  613. it('activates when a command is triggered on the active editor', async () => {
  614. const activationPromise = atom.packages.activatePackage('open-on-github')
  615. await atom.workspace.open()
  616. atom.commands.dispatch(atom.views.getView(atom.workspace.getActivePane()), 'open-on-github:file')
  617. await activationPromise
  618. })
  619. })