From 9978769ece9262265d3efa77357f9e8b46ad9a1e Mon Sep 17 00:00:00 2001 From: Erez Rokah Date: Mon, 11 Nov 2019 19:30:47 +0200 Subject: [PATCH] fix: make forkExists name matching case-insensitive (#2869) --- .../src/__tests__/implementation.spec.js | 75 +++++++++++++++++++ .../src/implementation.js | 4 +- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 packages/netlify-cms-backend-github/src/__tests__/implementation.spec.js diff --git a/packages/netlify-cms-backend-github/src/__tests__/implementation.spec.js b/packages/netlify-cms-backend-github/src/__tests__/implementation.spec.js new file mode 100644 index 00000000..64db7bc6 --- /dev/null +++ b/packages/netlify-cms-backend-github/src/__tests__/implementation.spec.js @@ -0,0 +1,75 @@ +import GitHubImplementation from '../implementation'; + +jest.spyOn(console, 'error').mockImplementation(() => {}); + +describe('github backend implementation', () => { + const config = { + getIn: jest.fn().mockImplementation(array => { + if (array[0] === 'backend' && array[1] === 'repo') { + return 'owner/repo'; + } + if (array[0] === 'backend' && array[1] === 'open_authoring') { + return false; + } + if (array[0] === 'backend' && array[1] === 'branch') { + return 'master'; + } + if (array[0] === 'backend' && array[1] === 'api_root') { + return 'https://api.github.com'; + } + }), + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('forkExists', () => { + it('should return true when repo is fork and parent matches originRepo', async () => { + const gitHubImplementation = new GitHubImplementation(config); + gitHubImplementation.currentUser = jest.fn().mockResolvedValue({ login: 'login' }); + + global.fetch = jest.fn().mockResolvedValue({ + // matching should be case-insensitive + json: () => ({ fork: true, parent: { full_name: 'OWNER/REPO' } }), + }); + + await expect(gitHubImplementation.forkExists({ token: 'token' })).resolves.toBe(true); + + expect(gitHubImplementation.currentUser).toHaveBeenCalledTimes(1); + expect(gitHubImplementation.currentUser).toHaveBeenCalledWith({ token: 'token' }); + expect(global.fetch).toHaveBeenCalledTimes(1); + expect(global.fetch).toHaveBeenCalledWith('https://api.github.com/repos/login/repo', { + method: 'GET', + headers: { + Authorization: 'token token', + }, + }); + }); + + it('should return false when repo is not a fork', async () => { + const gitHubImplementation = new GitHubImplementation(config); + gitHubImplementation.currentUser = jest.fn().mockResolvedValue({ login: 'login' }); + + global.fetch = jest.fn().mockResolvedValue({ + // matching should be case-insensitive + json: () => ({ fork: false }), + }); + + expect.assertions(1); + await expect(gitHubImplementation.forkExists({ token: 'token' })).resolves.toBe(false); + }); + + it("should return false when parent doesn't match originRepo", async () => { + const gitHubImplementation = new GitHubImplementation(config); + gitHubImplementation.currentUser = jest.fn().mockResolvedValue({ login: 'login' }); + + global.fetch = jest.fn().mockResolvedValue({ + json: () => ({ fork: true, parent: { full_name: 'owner/other_repo' } }), + }); + + expect.assertions(1); + await expect(gitHubImplementation.forkExists({ token: 'token' })).resolves.toBe(false); + }); + }); +}); diff --git a/packages/netlify-cms-backend-github/src/implementation.js b/packages/netlify-cms-backend-github/src/implementation.js index cc042429..a93e0ee8 100644 --- a/packages/netlify-cms-backend-github/src/implementation.js +++ b/packages/netlify-cms-backend-github/src/implementation.js @@ -167,7 +167,9 @@ export default class GitHub { // The parent and source objects are present when the repository is a fork. // parent is the repository this repository was forked from, source is the ultimate source for the network. const forkExists = - repo.fork === true && repo.parent && repo.parent.full_name === this.originRepo; + repo.fork === true && + repo.parent && + repo.parent.full_name.toLowerCase() === this.originRepo.toLowerCase(); return forkExists; } catch { return false;