fix(git-gateway): unpublished entries not loaded for git-gateway(GitHub) (#2856)
This commit is contained in:
parent
86adca3a18
commit
4a2328b2f1
@ -7,6 +7,7 @@ module.exports = {
|
|||||||
'netlify-cms-lib-auth': '<rootDir>/packages/netlify-cms-lib-auth/src/index.js',
|
'netlify-cms-lib-auth': '<rootDir>/packages/netlify-cms-lib-auth/src/index.js',
|
||||||
'netlify-cms-lib-util': '<rootDir>/packages/netlify-cms-lib-util/src/index.js',
|
'netlify-cms-lib-util': '<rootDir>/packages/netlify-cms-lib-util/src/index.js',
|
||||||
'netlify-cms-ui-default': '<rootDir>/packages/netlify-cms-ui-default/src/index.js',
|
'netlify-cms-ui-default': '<rootDir>/packages/netlify-cms-ui-default/src/index.js',
|
||||||
|
'netlify-cms-backend-github': '<rootDir>/packages/netlify-cms-backend-github/src/index.js',
|
||||||
},
|
},
|
||||||
testURL: 'http://localhost:8080',
|
testURL: 'http://localhost:8080',
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,7 @@ export default class API extends GithubAPI {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getRequestHeaders(headers = {}) {
|
requestHeaders(headers = {}) {
|
||||||
return this.tokenPromise().then(jwtToken => {
|
return this.tokenPromise().then(jwtToken => {
|
||||||
const baseHeader = {
|
const baseHeader = {
|
||||||
Authorization: `Bearer ${jwtToken}`,
|
Authorization: `Bearer ${jwtToken}`,
|
||||||
@ -53,38 +53,14 @@ export default class API extends GithubAPI {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
urlFor(path, options) {
|
handleRequestError(error, responseStatus) {
|
||||||
const cacheBuster = new Date().getTime();
|
throw new APIError(error.message || error.msg, responseStatus, 'Git Gateway');
|
||||||
const params = [`ts=${cacheBuster}`];
|
|
||||||
if (options.params) {
|
|
||||||
for (const key in options.params) {
|
|
||||||
params.push(`${key}=${encodeURIComponent(options.params[key])}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (params.length) {
|
|
||||||
path += `?${params.join('&')}`;
|
|
||||||
}
|
|
||||||
return this.api_root + path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
user() {
|
user() {
|
||||||
return Promise.resolve(this.commitAuthor);
|
return Promise.resolve(this.commitAuthor);
|
||||||
}
|
}
|
||||||
|
|
||||||
request(path, options = {}, parseResponse = response => this.parseResponse(response)) {
|
|
||||||
const url = this.urlFor(path, options);
|
|
||||||
let responseStatus;
|
|
||||||
return this.getRequestHeaders(options.headers || {})
|
|
||||||
.then(headers => fetch(url, { ...options, headers }))
|
|
||||||
.then(response => {
|
|
||||||
responseStatus = response.status;
|
|
||||||
return parseResponse(response);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
throw new APIError(error.message || error.msg, responseStatus, 'Git Gateway');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
commit(message, changeTree) {
|
commit(message, changeTree) {
|
||||||
const commitParams = {
|
const commitParams = {
|
||||||
message,
|
message,
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
import API from '../GitHubAPI';
|
||||||
|
|
||||||
|
describe('github API', () => {
|
||||||
|
describe('request', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const fetch = jest.fn();
|
||||||
|
global.fetch = fetch;
|
||||||
|
global.Date = jest.fn(() => ({ getTime: () => 1000 }));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch url with authorization header', async () => {
|
||||||
|
const api = new API({
|
||||||
|
api_root: 'https://site.netlify.com/.netlify/git/github',
|
||||||
|
tokenPromise: () => Promise.resolve('token'),
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch.mockResolvedValue({
|
||||||
|
text: jest.fn().mockResolvedValue('some response'),
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
headers: { get: () => '' },
|
||||||
|
});
|
||||||
|
const result = await api.request('/some-path');
|
||||||
|
expect(result).toEqual('some response');
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(1);
|
||||||
|
expect(fetch).toHaveBeenCalledWith(
|
||||||
|
'https://site.netlify.com/.netlify/git/github/some-path?ts=1000',
|
||||||
|
{
|
||||||
|
headers: { Authorization: 'Bearer token', 'Content-Type': 'application/json' },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error on not ok response with message property', async () => {
|
||||||
|
const api = new API({
|
||||||
|
api_root: 'https://site.netlify.com/.netlify/git/github',
|
||||||
|
tokenPromise: () => Promise.resolve('token'),
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch.mockResolvedValue({
|
||||||
|
text: jest.fn().mockResolvedValue({ message: 'some error' }),
|
||||||
|
ok: false,
|
||||||
|
status: 404,
|
||||||
|
headers: { get: () => '' },
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(api.request('some-path')).rejects.toThrow(
|
||||||
|
expect.objectContaining({
|
||||||
|
message: 'some error',
|
||||||
|
name: 'API_ERROR',
|
||||||
|
status: 404,
|
||||||
|
api: 'Git Gateway',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error on not ok response with msg property', async () => {
|
||||||
|
const api = new API({
|
||||||
|
api_root: 'https://site.netlify.com/.netlify/git/github',
|
||||||
|
tokenPromise: () => Promise.resolve('token'),
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch.mockResolvedValue({
|
||||||
|
text: jest.fn().mockResolvedValue({ msg: 'some error' }),
|
||||||
|
ok: false,
|
||||||
|
status: 404,
|
||||||
|
headers: { get: () => '' },
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(api.request('some-path')).rejects.toThrow(
|
||||||
|
expect.objectContaining({
|
||||||
|
message: 'some error',
|
||||||
|
name: 'API_ERROR',
|
||||||
|
status: 404,
|
||||||
|
api: 'Git Gateway',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -109,8 +109,13 @@ export default class API {
|
|||||||
return textPromise;
|
return textPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
request(path, options = {}, parseResponse = response => this.parseResponse(response)) {
|
handleRequestError(error, responseStatus) {
|
||||||
const headers = this.requestHeaders(options.headers || {});
|
throw new APIError(error.message, responseStatus, 'GitHub');
|
||||||
|
}
|
||||||
|
|
||||||
|
async request(path, options = {}, parseResponse = response => this.parseResponse(response)) {
|
||||||
|
// overriding classes can return a promise from requestHeaders
|
||||||
|
const headers = await this.requestHeaders(options.headers || {});
|
||||||
const url = this.urlFor(path, options);
|
const url = this.urlFor(path, options);
|
||||||
let responseStatus;
|
let responseStatus;
|
||||||
return fetch(url, { ...options, headers })
|
return fetch(url, { ...options, headers })
|
||||||
@ -118,13 +123,12 @@ export default class API {
|
|||||||
responseStatus = response.status;
|
responseStatus = response.status;
|
||||||
return parseResponse(response);
|
return parseResponse(response);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => this.handleRequestError(error, responseStatus));
|
||||||
throw new APIError(error.message, responseStatus, 'GitHub');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async requestAllPages(url, options = {}) {
|
async requestAllPages(url, options = {}) {
|
||||||
const headers = this.requestHeaders(options.headers || {});
|
// overriding classes can return a promise from requestHeaders
|
||||||
|
const headers = await this.requestHeaders(options.headers || {});
|
||||||
const processedURL = this.urlFor(url, options);
|
const processedURL = this.urlFor(url, options);
|
||||||
const allResponses = await getAllResponses(processedURL, { ...options, headers });
|
const allResponses = await getAllResponses(processedURL, { ...options, headers });
|
||||||
const pages = await Promise.all(allResponses.map(res => this.parseResponse(res)));
|
const pages = await Promise.all(allResponses.map(res => this.parseResponse(res)));
|
||||||
|
@ -36,4 +36,74 @@ describe('github API', () => {
|
|||||||
.then(() => prBaseBranch),
|
.then(() => prBaseBranch),
|
||||||
).resolves.toEqual('gh-pages');
|
).resolves.toEqual('gh-pages');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('request', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const fetch = jest.fn();
|
||||||
|
global.fetch = fetch;
|
||||||
|
global.Date = jest.fn(() => ({ getTime: () => 1000 }));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch url with authorization header', async () => {
|
||||||
|
const api = new API({ branch: 'gh-pages', repo: 'my-repo', token: 'token' });
|
||||||
|
|
||||||
|
fetch.mockResolvedValue({
|
||||||
|
text: jest.fn().mockResolvedValue('some response'),
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
headers: { get: () => '' },
|
||||||
|
});
|
||||||
|
const result = await api.request('/some-path');
|
||||||
|
expect(result).toEqual('some response');
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(1);
|
||||||
|
expect(fetch).toHaveBeenCalledWith('https://api.github.com/some-path?ts=1000', {
|
||||||
|
headers: { Authorization: 'token token', 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error on not ok response', async () => {
|
||||||
|
const api = new API({ branch: 'gh-pages', repo: 'my-repo', token: 'token' });
|
||||||
|
|
||||||
|
fetch.mockResolvedValue({
|
||||||
|
text: jest.fn().mockResolvedValue({ message: 'some error' }),
|
||||||
|
ok: false,
|
||||||
|
status: 404,
|
||||||
|
headers: { get: () => '' },
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(api.request('some-path')).rejects.toThrow(
|
||||||
|
expect.objectContaining({
|
||||||
|
message: 'some error',
|
||||||
|
name: 'API_ERROR',
|
||||||
|
status: 404,
|
||||||
|
api: 'GitHub',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow overriding requestHeaders to return a promise ', async () => {
|
||||||
|
const api = new API({ branch: 'gh-pages', repo: 'my-repo', token: 'token' });
|
||||||
|
|
||||||
|
api.requestHeaders = jest
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue({ Authorization: 'promise-token', 'Content-Type': 'application/json' });
|
||||||
|
|
||||||
|
fetch.mockResolvedValue({
|
||||||
|
text: jest.fn().mockResolvedValue('some response'),
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
headers: { get: () => '' },
|
||||||
|
});
|
||||||
|
const result = await api.request('/some-path');
|
||||||
|
expect(result).toEqual('some response');
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(1);
|
||||||
|
expect(fetch).toHaveBeenCalledWith('https://api.github.com/some-path?ts=1000', {
|
||||||
|
headers: { Authorization: 'promise-token', 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user