mirror of
https://github.com/codex-team/editor.js
synced 2024-05-19 06:47:16 +02:00
022320940e
* feat(conversion): allow to convert block using shortcut * display shortcuts in conversion toolbar * tests for the blocks.convert * tests for the toolbox shortcuts * Update CHANGELOG.md * Update toolbox.cy.ts * rm unused imports * firefox test fixed * test errors via to.throw
323 lines
8.6 KiB
TypeScript
323 lines
8.6 KiB
TypeScript
import type EditorJS from '../../../../types/index';
|
|
import { ConversionConfig, ToolboxConfig } from '../../../../types';
|
|
import ToolMock from '../../fixtures/tools/ToolMock';
|
|
|
|
/**
|
|
* There will be described test cases of 'blocks.*' API
|
|
*/
|
|
describe('api.blocks', () => {
|
|
const firstBlock = {
|
|
id: 'bwnFX5LoX7',
|
|
type: 'paragraph',
|
|
data: {
|
|
text: 'The first block content mock.',
|
|
},
|
|
};
|
|
const editorDataMock = {
|
|
blocks: [
|
|
firstBlock,
|
|
],
|
|
};
|
|
|
|
/**
|
|
* api.blocks.getById(id)
|
|
*/
|
|
describe('.getById()', () => {
|
|
/**
|
|
* Check that api.blocks.getByUd(id) returns the Block for existed id
|
|
*/
|
|
it('should return Block API for existed id', () => {
|
|
cy.createEditor({
|
|
data: editorDataMock,
|
|
}).as('editorInstance');
|
|
|
|
cy.get<EditorJS>('@editorInstance').then(async (editor) => {
|
|
const block = editor.blocks.getById(firstBlock.id);
|
|
|
|
expect(block).not.to.be.undefined;
|
|
expect(block.id).to.be.eq(firstBlock.id);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Check that api.blocks.getByUd(id) returns null for the not-existed id
|
|
*/
|
|
it('should return null for not-existed id', () => {
|
|
cy.createEditor({
|
|
data: editorDataMock,
|
|
}).as('editorInstance');
|
|
|
|
cy.get<EditorJS>('@editorInstance').then(async (editor) => {
|
|
expect(editor.blocks.getById('not-existed-id')).to.be.null;
|
|
});
|
|
});
|
|
});
|
|
|
|
/**
|
|
* api.blocks.update(id, newData)
|
|
*/
|
|
describe('.update()', () => {
|
|
/**
|
|
* Check if block is updated in DOM
|
|
*/
|
|
it('should update block in DOM', () => {
|
|
cy.createEditor({
|
|
data: editorDataMock,
|
|
}).as('editorInstance');
|
|
|
|
cy.get<EditorJS>('@editorInstance').then(async (editor) => {
|
|
const idToUpdate = firstBlock.id;
|
|
const newBlockData = {
|
|
text: 'Updated text',
|
|
};
|
|
|
|
editor.blocks.update(idToUpdate, newBlockData);
|
|
|
|
cy.get('[data-cy=editorjs]')
|
|
.get('div.ce-block')
|
|
.invoke('text')
|
|
.then(blockText => {
|
|
expect(blockText).to.be.eq(newBlockData.text);
|
|
});
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Check if block's data is updated after saving
|
|
*/
|
|
it('should update block in saved data', () => {
|
|
cy.createEditor({
|
|
data: editorDataMock,
|
|
}).as('editorInstance');
|
|
|
|
cy.get<EditorJS>('@editorInstance').then(async (editor) => {
|
|
const idToUpdate = firstBlock.id;
|
|
const newBlockData = {
|
|
text: 'Updated text',
|
|
};
|
|
|
|
editor.blocks.update(idToUpdate, newBlockData);
|
|
|
|
const output = await editor.save();
|
|
const text = output.blocks[0].data.text;
|
|
|
|
expect(text).to.be.eq(newBlockData.text);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* When incorrect id passed, editor should not update any block
|
|
*/
|
|
it('shouldn\'t update any block if not-existed id passed', () => {
|
|
cy.createEditor({
|
|
data: editorDataMock,
|
|
}).as('editorInstance');
|
|
|
|
cy.get<EditorJS>('@editorInstance').then(async (editor) => {
|
|
const idToUpdate = 'wrong-id-123';
|
|
const newBlockData = {
|
|
text: 'Updated text',
|
|
};
|
|
|
|
editor.blocks.update(idToUpdate, newBlockData);
|
|
|
|
cy.get('[data-cy=editorjs]')
|
|
.get('div.ce-block')
|
|
.invoke('text')
|
|
.then(blockText => {
|
|
expect(blockText).to.be.eq(firstBlock.data.text);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
/**
|
|
* api.blocks.insert(type, data, config, index, needToFocus, replace, id)
|
|
*/
|
|
describe('.insert()', function () {
|
|
it('should preserve block id if it is passed', function () {
|
|
cy.createEditor({
|
|
data: editorDataMock,
|
|
}).as('editorInstance');
|
|
|
|
cy.get<EditorJS>('@editorInstance').then(async (editor) => {
|
|
const type = 'paragraph';
|
|
const data = { text: 'codex' };
|
|
const config = undefined;
|
|
const index = undefined;
|
|
const needToFocus = undefined;
|
|
const replace = undefined;
|
|
const id = 'test-id-123';
|
|
|
|
const block = editor.blocks.insert(type, data, config, index, needToFocus, replace, id);
|
|
|
|
expect(block).not.to.be.undefined;
|
|
expect(block.id).to.be.eq(id);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('.convert()', function () {
|
|
it('should convert a Block to another type if original Tool has "conversionConfig.export" and target Tool has "conversionConfig.import"', function () {
|
|
/**
|
|
* Mock of Tool with conversionConfig
|
|
*/
|
|
class ConvertableTool extends ToolMock {
|
|
/**
|
|
* Specify how to import string data to this Tool
|
|
*/
|
|
public static get conversionConfig(): ConversionConfig {
|
|
return {
|
|
import: 'text',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Specify how to display Tool in a Toolbox
|
|
*/
|
|
public static get toolbox(): ToolboxConfig {
|
|
return {
|
|
icon: '',
|
|
title: 'Convertable tool',
|
|
};
|
|
}
|
|
}
|
|
|
|
const existingBlock = {
|
|
id: 'test-id-123',
|
|
type: 'paragraph',
|
|
data: {
|
|
text: 'Some text',
|
|
},
|
|
};
|
|
|
|
cy.createEditor({
|
|
tools: {
|
|
convertableTool: {
|
|
class: ConvertableTool,
|
|
},
|
|
},
|
|
data: {
|
|
blocks: [
|
|
existingBlock,
|
|
],
|
|
},
|
|
}).as('editorInstance');
|
|
|
|
/**
|
|
* Call the 'convert' api method
|
|
*/
|
|
cy.get<EditorJS>('@editorInstance')
|
|
.then(async (editor) => {
|
|
const { convert } = editor.blocks;
|
|
|
|
convert(existingBlock.id, 'convertableTool');
|
|
});
|
|
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting, @typescript-eslint/no-magic-numbers -- wait for block to be converted
|
|
cy.wait(100);
|
|
|
|
/**
|
|
* Check that block was converted
|
|
*/
|
|
cy.get<EditorJS>('@editorInstance')
|
|
.then(async (editor) => {
|
|
const { blocks } = await editor.save();
|
|
|
|
expect(blocks.length).to.eq(1);
|
|
expect(blocks[0].type).to.eq('convertableTool');
|
|
expect(blocks[0].data.text).to.eq(existingBlock.data.text);
|
|
});
|
|
});
|
|
|
|
it('should throw an error if nonexisting Block id passed', function () {
|
|
cy.createEditor({}).as('editorInstance');
|
|
|
|
/**
|
|
* Call the 'convert' api method with nonexisting Block id
|
|
*/
|
|
cy.get<EditorJS>('@editorInstance')
|
|
.then(async (editor) => {
|
|
const fakeId = 'WRNG_ID';
|
|
const { convert } = editor.blocks;
|
|
|
|
const exec = (): void => convert(fakeId, 'convertableTool');
|
|
|
|
expect(exec).to.throw(`Block with id "${fakeId}" not found`);
|
|
});
|
|
});
|
|
|
|
it('should throw an error if nonexisting Tool name passed', function () {
|
|
const existingBlock = {
|
|
id: 'test-id-123',
|
|
type: 'paragraph',
|
|
data: {
|
|
text: 'Some text',
|
|
},
|
|
};
|
|
|
|
cy.createEditor({
|
|
data: {
|
|
blocks: [
|
|
existingBlock,
|
|
],
|
|
},
|
|
}).as('editorInstance');
|
|
|
|
/**
|
|
* Call the 'convert' api method with nonexisting tool name
|
|
*/
|
|
cy.get<EditorJS>('@editorInstance')
|
|
.then(async (editor) => {
|
|
const nonexistingToolName = 'WRNG_TOOL_NAME';
|
|
const { convert } = editor.blocks;
|
|
|
|
const exec = (): void => convert(existingBlock.id, nonexistingToolName);
|
|
|
|
expect(exec).to.throw(`Block Tool with type "${nonexistingToolName}" not found`);
|
|
});
|
|
});
|
|
|
|
it('should throw an error if some tool does not provide "conversionConfig"', function () {
|
|
const existingBlock = {
|
|
id: 'test-id-123',
|
|
type: 'paragraph',
|
|
data: {
|
|
text: 'Some text',
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Mock of Tool without conversionConfig
|
|
*/
|
|
class ToolWithoutConversionConfig extends ToolMock {}
|
|
|
|
cy.createEditor({
|
|
tools: {
|
|
nonConvertableTool: {
|
|
class: ToolWithoutConversionConfig,
|
|
shortcut: 'CMD+SHIFT+H',
|
|
},
|
|
},
|
|
data: {
|
|
blocks: [
|
|
existingBlock,
|
|
],
|
|
},
|
|
}).as('editorInstance');
|
|
|
|
/**
|
|
* Call the 'convert' api method with tool that does not provide "conversionConfig"
|
|
*/
|
|
cy.get<EditorJS>('@editorInstance')
|
|
.then(async (editor) => {
|
|
const { convert } = editor.blocks;
|
|
|
|
const exec = (): void => convert(existingBlock.id, 'nonConvertableTool');
|
|
|
|
expect(exec).to.throw(`Conversion from "paragraph" to "nonConvertableTool" is not possible. NonConvertableTool tool(s) should provide a "conversionConfig"`);
|
|
});
|
|
});
|
|
});
|
|
});
|