feat: bundle assets with content (#2958)
* fix(media_folder_relative): use collection name in unpublished entry * refactor: pass arguments as object to AssetProxy ctor * feat: support media folders per collection * feat: resolve media files path based on entry path * fix: asset public path resolving * refactor: introduce typescript for AssetProxy * refactor: code cleanup * refactor(asset-proxy): add tests,switch to typescript,extract arguments * refactor: typescript for editorialWorkflow * refactor: add typescript for media library actions * refactor: fix type error on map set * refactor: move locale selector into reducer * refactor: add typescript for entries actions * refactor: remove duplication between asset store and media lib * feat: load assets from backend using API * refactor(github): add typescript, cache media files * fix: don't load media URL if already loaded * feat: add media folder config to collection * fix: load assets from API when not in UI state * feat: load entry media files when opening media library * fix: editorial workflow draft media files bug fixes * test(unit): fix unit tests * fix: editor control losing focus * style: add eslint object-shorthand rule * test(cypress): re-record mock data * fix: fix non github backends, large media * test: uncomment only in tests * fix(backend-test): add missing displayURL property * test(e2e): add media library tests * test(e2e): enable visual testing * test(e2e): add github backend media library tests * test(e2e): add git-gateway large media tests * chore: post rebase fixes * test: fix tests * test: fix tests * test(cypress): fix tests * docs: add media_folder docs * test(e2e): add media library delete test * test(e2e): try and fix image comparison on CI * ci: reduce test machines from 9 to 8 * test: add reducers and selectors unit tests * test(e2e): disable visual regression testing for now * test: add getAsset unit tests * refactor: use Asset class component instead of hooks * build: don't inline source maps * test: add more media path tests
This commit is contained in:
committed by
Shawn Erquhart
parent
7e4d4c1cc4
commit
2b41d8a838
@ -1,21 +1,19 @@
|
||||
const backend = 'github';
|
||||
|
||||
export const before = (taskResult, options) => {
|
||||
Cypress.config('taskTimeout', 5 * 60 * 1000);
|
||||
export const before = (taskResult, options, backend = 'github') => {
|
||||
Cypress.config('taskTimeout', 7 * 60 * 1000);
|
||||
cy.task('setupBackend', { backend, options }).then(data => {
|
||||
taskResult.data = data;
|
||||
Cypress.config('defaultCommandTimeout', data.mockResponses ? 5 * 1000 : 1 * 60 * 1000);
|
||||
});
|
||||
};
|
||||
|
||||
export const after = taskResult => {
|
||||
export const after = (taskResult, backend = 'github') => {
|
||||
cy.task('teardownBackend', {
|
||||
backend,
|
||||
...taskResult.data,
|
||||
});
|
||||
};
|
||||
|
||||
export const beforeEach = taskResult => {
|
||||
export const beforeEach = (taskResult, backend = 'github') => {
|
||||
const spec = Cypress.mocha.getRunner().suite.ctx.currentTest.parent.title;
|
||||
const testName = Cypress.mocha.getRunner().suite.ctx.currentTest.title;
|
||||
cy.task('setupBackendTest', {
|
||||
@ -34,7 +32,7 @@ export const beforeEach = taskResult => {
|
||||
return cy.clock(0, ['Date']);
|
||||
};
|
||||
|
||||
export const afterEach = taskResult => {
|
||||
export const afterEach = (taskResult, backend = 'github') => {
|
||||
const spec = Cypress.mocha.getRunner().suite.ctx.currentTest.parent.title;
|
||||
const testName = Cypress.mocha.getRunner().suite.ctx.currentTest.title;
|
||||
|
||||
|
169
cypress/integration/media/media_library.js
Normal file
169
cypress/integration/media/media_library.js
Normal file
@ -0,0 +1,169 @@
|
||||
import path from 'path';
|
||||
import '../../utils/dismiss-local-backup';
|
||||
import {
|
||||
login,
|
||||
goToMediaLibrary,
|
||||
newPost,
|
||||
populateEntry,
|
||||
exitEditor,
|
||||
goToWorkflow,
|
||||
updateWorkflowStatus,
|
||||
publishWorkflowEntry,
|
||||
goToEntry,
|
||||
goToCollections,
|
||||
} from '../../utils/steps';
|
||||
import { workflowStatus } from '../../utils/constants';
|
||||
|
||||
function uploadMediaFile() {
|
||||
assertNoImagesInLibrary();
|
||||
|
||||
const fixture = 'media/netlify.png';
|
||||
cy.fixture(fixture).then(fileContent => {
|
||||
cy.get('input[type="file"]').upload({
|
||||
fileContent,
|
||||
fileName: path.basename(fixture),
|
||||
mimeType: 'image/png',
|
||||
});
|
||||
});
|
||||
|
||||
cy.contains('span', 'Uploading...').should('not.exist');
|
||||
|
||||
assertImagesInLibrary();
|
||||
}
|
||||
|
||||
function assertImagesInLibrary() {
|
||||
cy.get('img[class*="CardImage"]').should('exist');
|
||||
}
|
||||
|
||||
function assertNoImagesInLibrary() {
|
||||
cy.get('img[class*="CardImage"]').should('not.exist');
|
||||
}
|
||||
|
||||
function deleteImage() {
|
||||
cy.get('img[class*="CardImage"]').click();
|
||||
cy.contains('button', 'Delete selected').click();
|
||||
assertNoImagesInLibrary();
|
||||
}
|
||||
|
||||
function chooseSelectedMediaFile() {
|
||||
cy.contains('button', 'Choose selected').click();
|
||||
}
|
||||
|
||||
function chooseAnImage() {
|
||||
cy.contains('button', 'Choose an image').click();
|
||||
}
|
||||
|
||||
function waitForEntryToLoad() {
|
||||
cy.contains('div', 'Loading entry...').should('not.exist');
|
||||
}
|
||||
|
||||
function matchImageSnapshot() {
|
||||
// cy.matchImageSnapshot();
|
||||
}
|
||||
|
||||
function newPostAndUploadImage() {
|
||||
newPost();
|
||||
chooseAnImage();
|
||||
uploadMediaFile();
|
||||
}
|
||||
|
||||
function newPostWithImage(entry) {
|
||||
newPostAndUploadImage();
|
||||
chooseSelectedMediaFile();
|
||||
populateEntry(entry);
|
||||
waitForEntryToLoad();
|
||||
}
|
||||
|
||||
function publishPostWithImage(entry) {
|
||||
newPostWithImage(entry);
|
||||
exitEditor();
|
||||
goToWorkflow();
|
||||
updateWorkflowStatus(entry, workflowStatus.draft, workflowStatus.ready);
|
||||
publishWorkflowEntry(entry);
|
||||
}
|
||||
|
||||
function closeMediaLibrary() {
|
||||
cy.get('button[class*="CloseButton"]').click();
|
||||
}
|
||||
|
||||
function switchToGridView() {
|
||||
cy.get('div[class*="ViewControls"]').within(() => {
|
||||
cy.get('button')
|
||||
.last()
|
||||
.click();
|
||||
});
|
||||
}
|
||||
|
||||
function assertGridEntryImage(entry) {
|
||||
cy.contains('li', entry.title).within(() => {
|
||||
cy.get('div[class*="CardImage"]').should('be.visible');
|
||||
});
|
||||
}
|
||||
|
||||
export default function({ entries, getUser }) {
|
||||
beforeEach(() => {
|
||||
login(getUser && getUser());
|
||||
});
|
||||
|
||||
it('can upload image from global media library', () => {
|
||||
goToMediaLibrary();
|
||||
uploadMediaFile();
|
||||
matchImageSnapshot();
|
||||
closeMediaLibrary();
|
||||
});
|
||||
|
||||
it('can delete image from global media library', () => {
|
||||
goToMediaLibrary();
|
||||
uploadMediaFile();
|
||||
closeMediaLibrary();
|
||||
goToMediaLibrary();
|
||||
deleteImage();
|
||||
matchImageSnapshot();
|
||||
closeMediaLibrary();
|
||||
});
|
||||
|
||||
it('can upload image from entry media library', () => {
|
||||
newPostAndUploadImage();
|
||||
matchImageSnapshot();
|
||||
closeMediaLibrary();
|
||||
exitEditor();
|
||||
});
|
||||
|
||||
it('can save entry with image', () => {
|
||||
newPostWithImage(entries[0]);
|
||||
matchImageSnapshot();
|
||||
exitEditor();
|
||||
});
|
||||
|
||||
it('can publish entry with image', () => {
|
||||
publishPostWithImage(entries[0]);
|
||||
goToEntry(entries[0]);
|
||||
waitForEntryToLoad();
|
||||
matchImageSnapshot();
|
||||
});
|
||||
|
||||
it('should not show draft entry image in global media library', () => {
|
||||
newPostWithImage(entries[0]);
|
||||
exitEditor();
|
||||
goToMediaLibrary();
|
||||
assertNoImagesInLibrary();
|
||||
matchImageSnapshot();
|
||||
});
|
||||
|
||||
it('should show published entry image in global media library', () => {
|
||||
publishPostWithImage(entries[0]);
|
||||
cy.clock().tick();
|
||||
goToMediaLibrary();
|
||||
assertImagesInLibrary();
|
||||
matchImageSnapshot();
|
||||
});
|
||||
|
||||
it('should show published entry image in grid view', () => {
|
||||
publishPostWithImage(entries[0]);
|
||||
goToCollections();
|
||||
switchToGridView();
|
||||
assertGridEntryImage(entries[0]);
|
||||
|
||||
matchImageSnapshot();
|
||||
});
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
import fixture from './media/media_library';
|
||||
import { entry1 } from './github/entries';
|
||||
import * as specUtils from './github/spec_utils';
|
||||
|
||||
const backend = 'git-gateway';
|
||||
|
||||
describe('Git Gateway Backend Media Library - Large Media', () => {
|
||||
let taskResult = { data: {} };
|
||||
|
||||
before(() => {
|
||||
specUtils.before(taskResult, {}, backend);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
specUtils.after(taskResult, backend);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
specUtils.beforeEach(taskResult, backend);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
specUtils.afterEach(taskResult, backend);
|
||||
});
|
||||
|
||||
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
|
||||
});
|
@ -0,0 +1,25 @@
|
||||
import fixture from './media/media_library';
|
||||
import { entry1 } from './github/entries';
|
||||
import * as specUtils from './github/spec_utils';
|
||||
|
||||
describe('GitHub Backend Media Library - GraphQL API', () => {
|
||||
let taskResult = { data: {} };
|
||||
|
||||
before(() => {
|
||||
specUtils.before(taskResult, { use_graphql: true });
|
||||
});
|
||||
|
||||
after(() => {
|
||||
specUtils.after(taskResult);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
specUtils.beforeEach(taskResult);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
specUtils.afterEach(taskResult);
|
||||
});
|
||||
|
||||
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
|
||||
});
|
@ -0,0 +1,25 @@
|
||||
import fixture from './media/media_library';
|
||||
import { entry1 } from './github/entries';
|
||||
import * as specUtils from './github/spec_utils';
|
||||
|
||||
describe('GitHub Backend Media Library - REST API', () => {
|
||||
let taskResult = { data: {} };
|
||||
|
||||
before(() => {
|
||||
specUtils.before(taskResult, { use_graphql: false });
|
||||
});
|
||||
|
||||
after(() => {
|
||||
specUtils.after(taskResult);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
specUtils.beforeEach(taskResult);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
specUtils.afterEach(taskResult);
|
||||
});
|
||||
|
||||
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
|
||||
});
|
21
cypress/integration/media_library_spec_test_backend.js
Normal file
21
cypress/integration/media_library_spec_test_backend.js
Normal file
@ -0,0 +1,21 @@
|
||||
import fixture from './media/media_library';
|
||||
|
||||
const entries = [
|
||||
{
|
||||
title: 'first title',
|
||||
body: 'first body',
|
||||
},
|
||||
];
|
||||
|
||||
describe('Test Backend Media Library', () => {
|
||||
after(() => {
|
||||
cy.task('teardownBackend', { backend: 'test' });
|
||||
});
|
||||
|
||||
before(() => {
|
||||
Cypress.config('defaultCommandTimeout', 4000);
|
||||
cy.task('setupBackend', { backend: 'test' });
|
||||
});
|
||||
|
||||
fixture({ entries });
|
||||
});
|
Reference in New Issue
Block a user