Feat: editorial workflow bitbucket gitlab (#3014)
* refactor: typescript the backends * feat: support multiple files upload for GitLab and BitBucket * fix: load entry media files from media folder or UI state * chore: cleanup log message * chore: code cleanup * refactor: typescript the test backend * refactor: cleanup getEntry unsued variables * refactor: moved shared backend code to lib util * chore: rename files to preserve history * fix: bind readFile method to API classes * test(e2e): switch to chrome in cypress tests * refactor: extract common api methods * refactor: remove most of immutable js usage from backends * feat(backend-gitlab): initial editorial workflow support * feat(backend-gitlab): implement missing workflow methods * chore: fix lint error * feat(backend-gitlab): support files deletion * test(e2e): add gitlab cypress tests * feat(backend-bitbucket): implement missing editorial workflow methods * test(e2e): add BitBucket backend e2e tests * build: update node version to 12 on netlify builds * fix(backend-bitbucket): extract BitBucket avatar url * test: fix git-gateway AuthenticationPage test * test(e2e): fix some backend tests * test(e2e): fix tests * test(e2e): add git-gateway editorial workflow test * chore: code cleanup * test(e2e): revert back to electron * test(e2e): add non editorial workflow tests * fix(git-gateway-gitlab): don't call unpublishedEntry in simple workflow gitlab git-gateway doesn't support editorial workflow APIs yet. This change makes sure not to call them in simple workflow * refactor(backend-bitbucket): switch to diffstat API instead of raw diff * chore: fix test * test(e2e): add more git-gateway tests * fix: post rebase typescript fixes * test(e2e): fix tests * fix: fix parsing of content key and add tests * refactor: rename test file * test(unit): add getStatues unit tests * chore: update cypress * docs: update beta docs
This commit is contained in:
committed by
Shawn Erquhart
parent
4ff5bc2ee0
commit
6f221ab3c1
@ -159,60 +159,6 @@ describe('github API', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMediaAsBlob', () => {
|
||||
it('should return response blob on non svg file', async () => {
|
||||
const api = new API({ branch: 'master', repo: 'owner/repo' });
|
||||
|
||||
const blob = {};
|
||||
api.readFile = jest.fn().mockResolvedValue(blob);
|
||||
|
||||
await expect(api.getMediaAsBlob('sha', 'static/media/image.png')).resolves.toBe(blob);
|
||||
|
||||
expect(api.readFile).toHaveBeenCalledTimes(1);
|
||||
expect(api.readFile).toHaveBeenCalledWith('static/media/image.png', 'sha', {
|
||||
parseText: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return text blob on svg file', async () => {
|
||||
const api = new API({ branch: 'master', repo: 'owner/repo' });
|
||||
|
||||
const text = 'svg';
|
||||
api.readFile = jest.fn().mockResolvedValue(text);
|
||||
|
||||
await expect(api.getMediaAsBlob('sha', 'static/media/logo.svg')).resolves.toEqual(
|
||||
new Blob([text], { type: 'image/svg+xml' }),
|
||||
);
|
||||
|
||||
expect(api.readFile).toHaveBeenCalledTimes(1);
|
||||
expect(api.readFile).toHaveBeenCalledWith('static/media/logo.svg', 'sha', {
|
||||
parseText: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMediaDisplayURL', () => {
|
||||
it('should return createObjectURL result', async () => {
|
||||
const api = new API({ branch: 'master', repo: 'owner/repo' });
|
||||
|
||||
const blob = {};
|
||||
api.getMediaAsBlob = jest.fn().mockResolvedValue(blob);
|
||||
global.URL.createObjectURL = jest
|
||||
.fn()
|
||||
.mockResolvedValue('blob:http://localhost:8080/blob-id');
|
||||
|
||||
await expect(api.getMediaDisplayURL('sha', 'static/media/image.png')).resolves.toBe(
|
||||
'blob:http://localhost:8080/blob-id',
|
||||
);
|
||||
|
||||
expect(api.getMediaAsBlob).toHaveBeenCalledTimes(1);
|
||||
expect(api.getMediaAsBlob).toHaveBeenCalledWith('sha', 'static/media/image.png');
|
||||
|
||||
expect(global.URL.createObjectURL).toHaveBeenCalledTimes(1);
|
||||
expect(global.URL.createObjectURL).toHaveBeenCalledWith(blob);
|
||||
});
|
||||
});
|
||||
|
||||
describe('persistFiles', () => {
|
||||
it('should update tree, commit and patch branch when useWorkflow is false', async () => {
|
||||
const api = new API({ branch: 'master', repo: 'owner/repo' });
|
||||
@ -572,4 +518,24 @@ describe('github API', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('should get preview statuses', async () => {
|
||||
const api = new API({ repo: 'repo' });
|
||||
|
||||
const statuses = [
|
||||
{ context: 'deploy', state: 'success', target_url: 'deploy-url' },
|
||||
{ context: 'build', state: 'error' },
|
||||
];
|
||||
|
||||
api.request = jest.fn(() => Promise.resolve({ statuses }));
|
||||
|
||||
const sha = 'sha';
|
||||
await expect(api.getStatuses(sha)).resolves.toEqual([
|
||||
{ context: 'deploy', state: 'success', target_url: 'deploy-url' },
|
||||
{ context: 'build', state: 'other' },
|
||||
]);
|
||||
|
||||
expect(api.request).toHaveBeenCalledTimes(1);
|
||||
expect(api.request).toHaveBeenCalledWith(`/repos/repo/commits/${sha}/status`);
|
||||
});
|
||||
});
|
||||
|
@ -44,27 +44,24 @@ describe('github GraphQL API', () => {
|
||||
expect(api.getAllFiles(entries, path)).toEqual([
|
||||
{
|
||||
name: 'post-1.md',
|
||||
sha: 'sha-1',
|
||||
id: 'sha-1',
|
||||
type: 'blob',
|
||||
size: 1,
|
||||
path: 'posts/post-1.md',
|
||||
blob: { size: 1 },
|
||||
},
|
||||
{
|
||||
name: 'post-2.md',
|
||||
sha: 'sha-2',
|
||||
id: 'sha-2',
|
||||
type: 'blob',
|
||||
size: 2,
|
||||
path: 'posts/post-2.md',
|
||||
blob: { size: 2 },
|
||||
},
|
||||
{
|
||||
name: 'nested-post.md',
|
||||
sha: 'nested-post-sha',
|
||||
id: 'nested-post-sha',
|
||||
type: 'blob',
|
||||
size: 3,
|
||||
path: 'posts/2019/nested-post.md',
|
||||
blob: { size: 3 },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
@ -4,20 +4,11 @@ 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';
|
||||
}
|
||||
}),
|
||||
backend: {
|
||||
repo: 'owner/repo',
|
||||
open_authoring: false,
|
||||
api_root: 'https://api.github.com',
|
||||
},
|
||||
};
|
||||
|
||||
const createObjectURL = jest.fn();
|
||||
@ -102,7 +93,7 @@ describe('github backend implementation', () => {
|
||||
};
|
||||
|
||||
expect.assertions(5);
|
||||
await expect(gitHubImplementation.persistMedia(mediaFile)).resolves.toEqual({
|
||||
await expect(gitHubImplementation.persistMedia(mediaFile, {})).resolves.toEqual({
|
||||
id: 0,
|
||||
name: 'image.png',
|
||||
size: 100,
|
||||
@ -140,9 +131,9 @@ describe('github backend implementation', () => {
|
||||
});
|
||||
|
||||
describe('loadEntryMediaFiles', () => {
|
||||
const getMediaAsBlob = jest.fn();
|
||||
const readFile = jest.fn();
|
||||
const mockAPI = {
|
||||
getMediaAsBlob,
|
||||
readFile,
|
||||
};
|
||||
|
||||
it('should return media files from meta data', async () => {
|
||||
@ -150,18 +141,17 @@ describe('github backend implementation', () => {
|
||||
gitHubImplementation.api = mockAPI;
|
||||
|
||||
const blob = new Blob(['']);
|
||||
getMediaAsBlob.mockResolvedValue(blob);
|
||||
readFile.mockResolvedValue(blob);
|
||||
|
||||
const file = new File([blob], name);
|
||||
|
||||
await expect(
|
||||
gitHubImplementation.loadEntryMediaFiles([
|
||||
{ path: 'static/media/image.png', sha: 'image.png' },
|
||||
gitHubImplementation.loadEntryMediaFiles('branch', [
|
||||
{ path: 'static/media/image.png', id: 'sha' },
|
||||
]),
|
||||
).resolves.toEqual([
|
||||
{
|
||||
id: 'image.png',
|
||||
sha: 'image.png',
|
||||
id: 'sha',
|
||||
displayURL: 'displayURL',
|
||||
path: 'static/media/image.png',
|
||||
name: 'image.png',
|
||||
@ -186,24 +176,27 @@ describe('github backend implementation', () => {
|
||||
gitHubImplementation.api = mockAPI;
|
||||
gitHubImplementation.loadEntryMediaFiles = jest
|
||||
.fn()
|
||||
.mockResolvedValue([{ path: 'image.png', sha: 'sha' }]);
|
||||
.mockResolvedValue([{ path: 'image.png', id: 'sha' }]);
|
||||
|
||||
generateContentKey.mockReturnValue('contentKey');
|
||||
|
||||
const data = {
|
||||
fileData: 'fileData',
|
||||
isModification: true,
|
||||
metaData: { objects: { entry: { path: 'entry-path' }, files: [{ path: 'image.png' }] } },
|
||||
metaData: {
|
||||
branch: 'branch',
|
||||
objects: { entry: { path: 'entry-path' }, files: [{ path: 'image.png', sha: 'sha' }] },
|
||||
},
|
||||
};
|
||||
readUnpublishedBranchFile.mockResolvedValue(data);
|
||||
|
||||
const collection = { get: jest.fn().mockReturnValue('posts') };
|
||||
const collection = 'posts';
|
||||
await expect(gitHubImplementation.unpublishedEntry(collection, 'slug')).resolves.toEqual({
|
||||
slug: 'slug',
|
||||
file: { path: 'entry-path' },
|
||||
file: { path: 'entry-path', id: null },
|
||||
data: 'fileData',
|
||||
metaData: { objects: { entry: { path: 'entry-path' }, files: [{ path: 'image.png' }] } },
|
||||
mediaFiles: [{ path: 'image.png', sha: 'sha' }],
|
||||
metaData: data.metaData,
|
||||
mediaFiles: [{ path: 'image.png', id: 'sha' }],
|
||||
isModification: true,
|
||||
});
|
||||
|
||||
@ -214,9 +207,9 @@ describe('github backend implementation', () => {
|
||||
expect(readUnpublishedBranchFile).toHaveBeenCalledWith('contentKey');
|
||||
|
||||
expect(gitHubImplementation.loadEntryMediaFiles).toHaveBeenCalledTimes(1);
|
||||
expect(gitHubImplementation.loadEntryMediaFiles).toHaveBeenCalledWith(
|
||||
data.metaData.objects.files,
|
||||
);
|
||||
expect(gitHubImplementation.loadEntryMediaFiles).toHaveBeenCalledWith('branch', [
|
||||
{ path: 'image.png', id: 'sha' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user