mirror of
https://github.com/codex-team/editor.js
synced 2026-03-16 07:35:48 +01:00
fix: write tests for tooltip.ts and fix lint issues
This commit is contained in:
parent
3ec36a5d7c
commit
f02e838dc7
45 changed files with 2109 additions and 459 deletions
|
|
@ -10,8 +10,44 @@ export const selectionChangeDebounceTimeout = 180;
|
|||
*/
|
||||
export const modificationsObserverBatchTimeout = 400;
|
||||
|
||||
/**
|
||||
* The data-interface attribute name
|
||||
* Used as a single source of truth for the data-interface attribute
|
||||
*/
|
||||
export const DATA_INTERFACE_ATTRIBUTE = 'data-interface';
|
||||
|
||||
/**
|
||||
* Value for the data-interface attribute on editor wrapper elements
|
||||
* Used as a single source of truth for editor identification
|
||||
*/
|
||||
export const EDITOR_INTERFACE_VALUE = 'editorjs';
|
||||
|
||||
/**
|
||||
* Value for the data-interface attribute on inline toolbar elements
|
||||
* Used as a single source of truth for inline toolbar identification
|
||||
*/
|
||||
export const INLINE_TOOLBAR_INTERFACE_VALUE = 'inline-toolbar';
|
||||
|
||||
/**
|
||||
* Value for the data-interface attribute on tooltip elements
|
||||
* Used as a single source of truth for tooltip identification
|
||||
*/
|
||||
export const TOOLTIP_INTERFACE_VALUE = 'tooltip';
|
||||
|
||||
/**
|
||||
* CSS selector for the main editor wrapper element
|
||||
* Used to identify the editor container in the DOM
|
||||
*/
|
||||
export const EDITOR_INTERFACE_SELECTOR = '[data-interface=editorjs]';
|
||||
|
||||
/**
|
||||
* CSS selector for tooltip elements
|
||||
* Used to identify tooltip elements in the DOM
|
||||
*/
|
||||
export const TOOLTIP_INTERFACE_SELECTOR = '[data-interface="tooltip"]';
|
||||
|
||||
/**
|
||||
* CSS selector for inline toolbar elements
|
||||
* Used to identify inline toolbar elements in the DOM
|
||||
*/
|
||||
export const INLINE_TOOLBAR_INTERFACE_SELECTOR = '[data-interface=inline-toolbar]';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Tooltip as ITooltip } from '../../../../types/api';
|
||||
import type { TooltipOptions, TooltipContent } from 'codex-tooltip/types';
|
||||
import type { TooltipOptions, TooltipContent } from '../../utils/tooltip';
|
||||
import Module from '../../__module';
|
||||
import type { ModuleConfig } from '../../../types-internal/module-config';
|
||||
import * as tooltip from '../../utils/tooltip';
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import type { Popover, PopoverItemHtmlParams, PopoverItemParams, WithChildren }
|
|||
import { PopoverItemType } from '../../utils/popover';
|
||||
import { PopoverInline } from '../../utils/popover/popover-inline';
|
||||
import type InlineToolAdapter from 'src/components/tools/inline';
|
||||
import { DATA_INTERFACE_ATTRIBUTE, INLINE_TOOLBAR_INTERFACE_VALUE } from '../../constants';
|
||||
|
||||
/**
|
||||
* Inline Toolbar elements
|
||||
|
|
@ -159,7 +160,7 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
|||
...(this.isRtl ? [ this.Editor.UI.CSS.editorRtlFix ] : []),
|
||||
]);
|
||||
|
||||
this.nodes.wrapper.setAttribute('data-interface', 'inline-toolbar');
|
||||
this.nodes.wrapper.setAttribute(DATA_INTERFACE_ATTRIBUTE, INLINE_TOOLBAR_INTERFACE_VALUE);
|
||||
this.nodes.wrapper.setAttribute('data-cy', 'inline-toolbar');
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { mobileScreenBreakpoint } from '../utils';
|
|||
|
||||
import styles from '../../styles/main.css?inline';
|
||||
import { BlockHovered } from '../events/BlockHovered';
|
||||
import { selectionChangeDebounceTimeout } from '../constants';
|
||||
import { DATA_INTERFACE_ATTRIBUTE, EDITOR_INTERFACE_VALUE, selectionChangeDebounceTimeout } from '../constants';
|
||||
import { EditorMobileLayoutToggled } from '../events';
|
||||
/**
|
||||
* HTML Elements used for UI
|
||||
|
|
@ -288,7 +288,7 @@ export default class UI extends Module<UINodes> {
|
|||
this.CSS.editorWrapper,
|
||||
...(this.isRtl ? [ this.CSS.editorRtlFix ] : []),
|
||||
]);
|
||||
this.nodes.wrapper.setAttribute('data-interface', 'editorjs');
|
||||
this.nodes.wrapper.setAttribute(DATA_INTERFACE_ATTRIBUTE, EDITOR_INTERFACE_VALUE);
|
||||
this.nodes.redactor = $.make('div', this.CSS.editorZone);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,71 +1,616 @@
|
|||
/* eslint-disable jsdoc/no-undefined-types */
|
||||
/**
|
||||
* Use external module CodeX Tooltip
|
||||
*/
|
||||
import CodeXTooltips from 'codex-tooltip';
|
||||
import type { TooltipOptions, TooltipContent } from 'codex-tooltip/types';
|
||||
import tooltipStyles from '../../styles/tooltip.css?inline';
|
||||
import { DATA_INTERFACE_ATTRIBUTE, TOOLTIP_INTERFACE_VALUE } from '../constants';
|
||||
|
||||
/**
|
||||
* Tooltips lib: CodeX Tooltips
|
||||
*
|
||||
* @see https://github.com/codex-team/codex.tooltips
|
||||
* Tooltip supported content
|
||||
*/
|
||||
let lib: null | CodeXTooltips = null;
|
||||
export type TooltipContent = HTMLElement | DocumentFragment | Node | string;
|
||||
|
||||
/**
|
||||
* If library is needed, but it is not initialized yet, this function will initialize it
|
||||
*
|
||||
* For example, if editor was destroyed and then initialized again
|
||||
* Base options interface for tooltips
|
||||
*/
|
||||
function prepare(): void {
|
||||
if (lib) {
|
||||
return;
|
||||
export interface TooltipOptions {
|
||||
/**
|
||||
* Tooltip placement: top|bottom|left|right
|
||||
*/
|
||||
placement?: string;
|
||||
|
||||
/**
|
||||
* Tooltip top margin
|
||||
*/
|
||||
marginTop?: number;
|
||||
|
||||
/**
|
||||
* Tooltip left margin
|
||||
*/
|
||||
marginLeft?: number;
|
||||
|
||||
/**
|
||||
* Tooltip right margin
|
||||
*/
|
||||
marginRight?: number;
|
||||
|
||||
/**
|
||||
* Tooltip bottom margin
|
||||
*/
|
||||
marginBottom?: number;
|
||||
|
||||
/**
|
||||
* Timout before showing
|
||||
*/
|
||||
delay?: number;
|
||||
|
||||
/**
|
||||
* Timout before hiding
|
||||
*/
|
||||
hidingDelay?: number;
|
||||
}
|
||||
|
||||
const DEFAULT_OFFSET = 10;
|
||||
const TOOLTIP_ROLE = 'tooltip';
|
||||
const ARIA_HIDDEN_ATTRIBUTE = 'aria-hidden';
|
||||
const ARIA_HIDDEN_FALSE = 'false';
|
||||
const ARIA_HIDDEN_TRUE = 'true';
|
||||
const VISIBILITY_PROPERTY = 'visibility';
|
||||
const VISIBILITY_VISIBLE = 'visible';
|
||||
const VISIBILITY_HIDDEN = 'hidden';
|
||||
|
||||
type CSSTooltipClasses = {
|
||||
tooltip: string;
|
||||
tooltipContent: string;
|
||||
tooltipShown: string;
|
||||
placement: {
|
||||
left: string;
|
||||
bottom: string;
|
||||
right: string;
|
||||
top: string;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Tiny any beautiful tooltips module.
|
||||
*
|
||||
* Can be showed near passed Element with any specified HTML content
|
||||
*
|
||||
* Based on codex-tooltip: https://github.com/codex-team/codex.tooltips
|
||||
*
|
||||
* @author CodeX <codex.so>
|
||||
* @license MIT
|
||||
*/
|
||||
class Tooltip {
|
||||
/**
|
||||
* Tooltip CSS classes
|
||||
*
|
||||
* @returns {object} CSS class names
|
||||
*/
|
||||
private get CSS(): CSSTooltipClasses {
|
||||
return {
|
||||
tooltip: 'ct',
|
||||
tooltipContent: 'ct__content',
|
||||
tooltipShown: 'ct--shown',
|
||||
placement: {
|
||||
left: 'ct--left',
|
||||
bottom: 'ct--bottom',
|
||||
right: 'ct--right',
|
||||
top: 'ct--top',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
lib = new CodeXTooltips();
|
||||
/**
|
||||
* Module nodes
|
||||
*/
|
||||
private nodes: {
|
||||
wrapper: HTMLElement | null;
|
||||
content: HTMLElement | null;
|
||||
} = {
|
||||
wrapper: null,
|
||||
content: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Appearance state
|
||||
*/
|
||||
private showed: boolean = false;
|
||||
|
||||
/**
|
||||
* Offset above the Tooltip
|
||||
*/
|
||||
private offsetTop: number = DEFAULT_OFFSET;
|
||||
|
||||
/**
|
||||
* Offset at the left from the Tooltip
|
||||
*/
|
||||
private offsetLeft: number = DEFAULT_OFFSET;
|
||||
|
||||
/**
|
||||
* Offset at the right from the Tooltip
|
||||
*/
|
||||
private offsetRight: number = DEFAULT_OFFSET;
|
||||
|
||||
/**
|
||||
* Store timeout before showing to clear it on hide
|
||||
*/
|
||||
private showingTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
/**
|
||||
* How many milliseconds need to wait before hiding
|
||||
*/
|
||||
private hidingDelay: number = 0;
|
||||
|
||||
/**
|
||||
* Store timeout before hiding
|
||||
*/
|
||||
private hidingTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
/**
|
||||
* MutationObserver for watching tooltip visibility changes
|
||||
*/
|
||||
private ariaObserver: MutationObserver | null = null;
|
||||
|
||||
/**
|
||||
* Static singleton instance
|
||||
*/
|
||||
private static instance: Tooltip | null = null;
|
||||
|
||||
/**
|
||||
* Get singleton instance
|
||||
*/
|
||||
public static getInstance(): Tooltip {
|
||||
if (!Tooltip.instance) {
|
||||
Tooltip.instance = new Tooltip();
|
||||
}
|
||||
|
||||
return Tooltip.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Module constructor
|
||||
*/
|
||||
private constructor() {
|
||||
this.loadStyles();
|
||||
this.prepare();
|
||||
|
||||
window.addEventListener('scroll', this.handleWindowScroll, { passive: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Tooltip near passed element with specified HTML content
|
||||
*
|
||||
* @param {HTMLElement} element - target element to place Tooltip near that
|
||||
* @param {TooltipContent} content — any HTML Element of String that will be used as content
|
||||
* @param {TooltipOptions} options — Available options {@link TooltipOptions}
|
||||
*/
|
||||
public show(element: HTMLElement, content: TooltipContent, options: TooltipOptions = {}): void {
|
||||
if (!this.nodes.wrapper) {
|
||||
this.prepare();
|
||||
}
|
||||
|
||||
if (this.hidingTimeout) {
|
||||
clearTimeout(this.hidingTimeout);
|
||||
this.hidingTimeout = null;
|
||||
}
|
||||
|
||||
const basicOptions = {
|
||||
placement: 'bottom',
|
||||
marginTop: 0,
|
||||
marginLeft: 0,
|
||||
marginRight: 0,
|
||||
marginBottom: 0,
|
||||
delay: 70,
|
||||
hidingDelay: 0,
|
||||
};
|
||||
const showingOptions = Object.assign(basicOptions, options);
|
||||
|
||||
if (showingOptions.hidingDelay) {
|
||||
this.hidingDelay = showingOptions.hidingDelay;
|
||||
}
|
||||
|
||||
if (!this.nodes.content) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.nodes.content.innerHTML = '';
|
||||
|
||||
if (typeof content === 'string') {
|
||||
this.nodes.content.appendChild(document.createTextNode(content));
|
||||
} else if (content instanceof Node) {
|
||||
this.nodes.content.appendChild(content);
|
||||
} else {
|
||||
throw Error('[CodeX Tooltip] Wrong type of «content» passed. It should be an instance of Node or String. ' +
|
||||
'But ' + typeof content + ' given.');
|
||||
}
|
||||
|
||||
if (!this.nodes.wrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.nodes.wrapper.classList.remove(...Object.values(this.CSS.placement));
|
||||
|
||||
switch (showingOptions.placement) {
|
||||
case 'top':
|
||||
this.placeTop(element, showingOptions);
|
||||
break;
|
||||
|
||||
case 'left':
|
||||
this.placeLeft(element, showingOptions);
|
||||
break;
|
||||
|
||||
case 'right':
|
||||
this.placeRight(element, showingOptions);
|
||||
break;
|
||||
|
||||
case 'bottom':
|
||||
default:
|
||||
this.placeBottom(element, showingOptions);
|
||||
break;
|
||||
}
|
||||
|
||||
if (showingOptions && showingOptions.delay) {
|
||||
this.showingTimeout = setTimeout(() => {
|
||||
if (this.nodes.wrapper) {
|
||||
this.nodes.wrapper.classList.add(this.CSS.tooltipShown);
|
||||
this.updateTooltipVisibility();
|
||||
}
|
||||
this.showed = true;
|
||||
}, showingOptions.delay);
|
||||
} else {
|
||||
if (this.nodes.wrapper) {
|
||||
this.nodes.wrapper.classList.add(this.CSS.tooltipShown);
|
||||
this.updateTooltipVisibility();
|
||||
}
|
||||
this.showed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide toolbox tooltip and clean content
|
||||
*
|
||||
* @param {boolean} skipDelay - forces hiding immediately
|
||||
*/
|
||||
public hide(skipDelay: boolean = false): void {
|
||||
if (this.hidingDelay && !skipDelay) {
|
||||
// debounce
|
||||
if (this.hidingTimeout) {
|
||||
clearTimeout(this.hidingTimeout);
|
||||
}
|
||||
|
||||
this.hidingTimeout = setTimeout(() => {
|
||||
this.hide(true);
|
||||
}, this.hidingDelay);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.nodes.wrapper) {
|
||||
this.nodes.wrapper.classList.remove(this.CSS.tooltipShown);
|
||||
this.updateTooltipVisibility();
|
||||
}
|
||||
this.showed = false;
|
||||
|
||||
if (this.showingTimeout) {
|
||||
clearTimeout(this.showingTimeout);
|
||||
this.showingTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouseover/Mouseleave decorator
|
||||
*
|
||||
* @param {HTMLElement} element - target element to place Tooltip near that
|
||||
* @param {TooltipContent} content — any HTML Element of String that will be used as content
|
||||
* @param {TooltipOptions} options — Available options {@link TooltipOptions}
|
||||
*/
|
||||
public onHover(element: HTMLElement, content: TooltipContent, options: TooltipOptions = {}): void {
|
||||
element.addEventListener('mouseenter', () => {
|
||||
this.show(element, content, options);
|
||||
});
|
||||
element.addEventListener('mouseleave', () => {
|
||||
this.hide();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Release DOM and event listeners
|
||||
*/
|
||||
public destroy(): void {
|
||||
this.ariaObserver?.disconnect();
|
||||
this.ariaObserver = null;
|
||||
|
||||
if (this.nodes.wrapper) {
|
||||
this.nodes.wrapper.remove();
|
||||
}
|
||||
|
||||
window.removeEventListener('scroll', this.handleWindowScroll);
|
||||
|
||||
Tooltip.instance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide tooltip when page is scrolled
|
||||
*/
|
||||
private handleWindowScroll = (): void => {
|
||||
if (this.showed) {
|
||||
this.hide(true);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Module Preparation method
|
||||
*/
|
||||
private prepare(): void {
|
||||
this.nodes.wrapper = this.make('div', this.CSS.tooltip);
|
||||
this.nodes.wrapper.setAttribute(DATA_INTERFACE_ATTRIBUTE, TOOLTIP_INTERFACE_VALUE);
|
||||
this.nodes.content = this.make('div', this.CSS.tooltipContent);
|
||||
|
||||
if (this.nodes.wrapper && this.nodes.content) {
|
||||
this.append(this.nodes.wrapper, this.nodes.content);
|
||||
this.append(document.body, this.nodes.wrapper);
|
||||
this.ensureTooltipAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update tooltip visibility based on shown state
|
||||
*/
|
||||
private updateTooltipVisibility(): void {
|
||||
if (!this.nodes.wrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isShown = this.nodes.wrapper.classList.contains(this.CSS.tooltipShown);
|
||||
|
||||
this.nodes.wrapper.style.setProperty(VISIBILITY_PROPERTY, isShown ? VISIBILITY_VISIBLE : VISIBILITY_HIDDEN);
|
||||
this.nodes.wrapper.setAttribute(ARIA_HIDDEN_ATTRIBUTE, isShown ? ARIA_HIDDEN_FALSE : ARIA_HIDDEN_TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch tooltip visibility changes for accessibility
|
||||
*/
|
||||
private watchTooltipVisibility(): void {
|
||||
if (!this.nodes.wrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.ariaObserver?.disconnect();
|
||||
|
||||
this.updateTooltipVisibility();
|
||||
|
||||
this.ariaObserver = new MutationObserver(() => {
|
||||
this.updateTooltipVisibility();
|
||||
});
|
||||
|
||||
this.ariaObserver.observe(this.nodes.wrapper, {
|
||||
attributes: true,
|
||||
attributeFilter: [ 'class' ],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure tooltip has proper accessibility attributes
|
||||
*/
|
||||
private ensureTooltipAttributes(): void {
|
||||
if (!this.nodes.wrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.nodes.wrapper.hasAttribute(DATA_INTERFACE_ATTRIBUTE) || this.nodes.wrapper.getAttribute(DATA_INTERFACE_ATTRIBUTE) !== TOOLTIP_INTERFACE_VALUE) {
|
||||
this.nodes.wrapper.setAttribute(DATA_INTERFACE_ATTRIBUTE, TOOLTIP_INTERFACE_VALUE);
|
||||
}
|
||||
|
||||
this.nodes.wrapper.setAttribute('role', TOOLTIP_ROLE);
|
||||
this.watchTooltipVisibility();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append CSS file
|
||||
*/
|
||||
private loadStyles(): void {
|
||||
const id = 'codex-tooltips-style';
|
||||
|
||||
if (document.getElementById(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tag = this.make('style', null, {
|
||||
textContent: tooltipStyles,
|
||||
id,
|
||||
});
|
||||
|
||||
/**
|
||||
* Append styles at the top of HEAD tag
|
||||
*/
|
||||
this.prepend(document.head, tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates element coords and moves tooltip bottom of the element
|
||||
*
|
||||
* @param {HTMLElement} element - target element
|
||||
* @param {TooltipOptions} showingOptions - placement options
|
||||
*/
|
||||
private placeBottom(element: HTMLElement, showingOptions: TooltipOptions): void {
|
||||
if (!this.nodes.wrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elementCoords = element.getBoundingClientRect();
|
||||
const left = elementCoords.left + element.clientWidth / 2 - this.nodes.wrapper.offsetWidth / 2;
|
||||
const top = elementCoords.bottom + window.pageYOffset + this.offsetTop + (showingOptions.marginTop ?? 0);
|
||||
|
||||
this.applyPlacement('bottom', left, top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates element coords and moves tooltip top of the element
|
||||
*
|
||||
* @param {HTMLElement} element - target element
|
||||
* @param {TooltipOptions} _showingOptions - placement options (unused for top placement)
|
||||
*/
|
||||
private placeTop(element: HTMLElement, _showingOptions: TooltipOptions): void {
|
||||
if (!this.nodes.wrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elementCoords = element.getBoundingClientRect();
|
||||
const left = elementCoords.left + element.clientWidth / 2 - this.nodes.wrapper.offsetWidth / 2;
|
||||
const top = elementCoords.top + window.pageYOffset - this.nodes.wrapper.clientHeight - this.offsetTop;
|
||||
|
||||
this.applyPlacement('top', left, top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates element coords and moves tooltip left of the element
|
||||
*
|
||||
* @param {HTMLElement} element - target element
|
||||
* @param {TooltipOptions} showingOptions - placement options
|
||||
*/
|
||||
private placeLeft(element: HTMLElement, showingOptions: TooltipOptions): void {
|
||||
if (!this.nodes.wrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elementCoords = element.getBoundingClientRect();
|
||||
const left = elementCoords.left - this.nodes.wrapper.offsetWidth - this.offsetLeft - (showingOptions.marginLeft ?? 0);
|
||||
const top = elementCoords.top + window.pageYOffset + element.clientHeight / 2 - this.nodes.wrapper.offsetHeight / 2;
|
||||
|
||||
this.applyPlacement('left', left, top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates element coords and moves tooltip right of the element
|
||||
*
|
||||
* @param {HTMLElement} element - target element
|
||||
* @param {TooltipOptions} showingOptions - placement options
|
||||
*/
|
||||
private placeRight(element: HTMLElement, showingOptions: TooltipOptions): void {
|
||||
if (!this.nodes.wrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elementCoords = element.getBoundingClientRect();
|
||||
const left = elementCoords.right + this.offsetRight + (showingOptions.marginRight ?? 0);
|
||||
const top = elementCoords.top + window.pageYOffset + element.clientHeight / 2 - this.nodes.wrapper.offsetHeight / 2;
|
||||
|
||||
this.applyPlacement('right', left, top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set wrapper position
|
||||
*
|
||||
* @param {string} place - placement direction
|
||||
* @param {number} left - left position in pixels
|
||||
* @param {number} top - top position in pixels
|
||||
*/
|
||||
private applyPlacement(place: 'top' | 'bottom' | 'left' | 'right', left: number, top: number): void {
|
||||
if (!this.nodes.wrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.nodes.wrapper.classList.add(this.CSS.placement[place]);
|
||||
|
||||
this.nodes.wrapper.style.left = `${left}px`;
|
||||
this.nodes.wrapper.style.top = `${top}px`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for making Elements with classname and attributes
|
||||
*
|
||||
* @param {string} tagName - new Element tag name
|
||||
* @param {Array<string>|string} classNames - list or name of CSS classname(s)
|
||||
* @param {object} attributes - any attributes
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
private make(tagName: string, classNames: string | string[] | null = null, attributes: Record<string, unknown> = {}): HTMLElement {
|
||||
const el = document.createElement(tagName);
|
||||
|
||||
if (Array.isArray(classNames)) {
|
||||
el.classList.add(...classNames);
|
||||
} else if (classNames) {
|
||||
el.classList.add(classNames);
|
||||
}
|
||||
|
||||
for (const attrName in attributes) {
|
||||
if (Object.prototype.hasOwnProperty.call(attributes, attrName)) {
|
||||
(el as unknown as Record<string, unknown>)[attrName] = attributes[attrName];
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append one or several elements to the parent
|
||||
*
|
||||
* @param {Element|DocumentFragment} parent - where to append
|
||||
* @param {Element|Element[]} elements - element or elements list
|
||||
*/
|
||||
private append(parent: Element | DocumentFragment, elements: Element | Element[] | DocumentFragment): void {
|
||||
if (Array.isArray(elements)) {
|
||||
elements.forEach((el) => parent.appendChild(el));
|
||||
} else {
|
||||
parent.appendChild(elements);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append element or a couple to the beginning of the parent elements
|
||||
*
|
||||
* @param {Element} parent - where to append
|
||||
* @param {Element|Element[]} elements - element or elements list
|
||||
*/
|
||||
private prepend(parent: Element, elements: Element | Element[]): void {
|
||||
if (Array.isArray(elements)) {
|
||||
const reversed = elements.reverse();
|
||||
|
||||
reversed.forEach((el) => parent.prepend(el));
|
||||
} else {
|
||||
parent.prepend(elements);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows tooltip on element with passed HTML content
|
||||
* Get singleton tooltip instance
|
||||
*/
|
||||
const getTooltip = (): Tooltip => {
|
||||
return Tooltip.getInstance();
|
||||
};
|
||||
|
||||
/**
|
||||
* Show tooltip near element with specified content
|
||||
*
|
||||
* @param {HTMLElement} element - any HTML element in DOM
|
||||
* @param content - tooltip's content
|
||||
* @param options - showing settings
|
||||
* @param {HTMLElement} element - target element to place tooltip near
|
||||
* @param {TooltipContent} content - tooltip content
|
||||
* @param {TooltipOptions} options - tooltip options
|
||||
*/
|
||||
export function show(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void {
|
||||
prepare();
|
||||
|
||||
lib?.show(element, content, options);
|
||||
}
|
||||
export const show = (element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void => {
|
||||
getTooltip().show(element, content, options ?? {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides tooltip
|
||||
* Hide tooltip
|
||||
*
|
||||
* @param skipHidingDelay — pass true to immediately hide the tooltip
|
||||
* @param {boolean} skipHidingDelay - forces hiding immediately
|
||||
*/
|
||||
export function hide(skipHidingDelay = false): void {
|
||||
prepare();
|
||||
|
||||
lib?.hide(skipHidingDelay);
|
||||
}
|
||||
export const hide = (skipHidingDelay = false): void => {
|
||||
getTooltip().hide(skipHidingDelay);
|
||||
};
|
||||
|
||||
/**
|
||||
* Binds 'mouseenter' and 'mouseleave' events that shows/hides the Tooltip
|
||||
* Show tooltip on hover (mouseenter/mouseleave)
|
||||
*
|
||||
* @param {HTMLElement} element - any HTML element in DOM
|
||||
* @param content - tooltip's content
|
||||
* @param options - showing settings
|
||||
* @param {HTMLElement} element - target element to place tooltip near
|
||||
* @param {TooltipContent} content - tooltip content
|
||||
* @param {TooltipOptions} options - tooltip options
|
||||
*/
|
||||
export function onHover(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void {
|
||||
prepare();
|
||||
|
||||
lib?.onHover(element, content, options);
|
||||
}
|
||||
export const onHover = (element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void => {
|
||||
getTooltip().onHover(element, content, options ?? {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Release the library
|
||||
* Destroy tooltip instance and clean up
|
||||
*/
|
||||
export function destroy(): void {
|
||||
lib?.destroy();
|
||||
lib = null;
|
||||
}
|
||||
export const destroy = (): void => {
|
||||
getTooltip().destroy();
|
||||
};
|
||||
|
|
|
|||
105
src/styles/tooltip.css
Normal file
105
src/styles/tooltip.css
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
:root {
|
||||
--ct-color-bg: #1d202b;
|
||||
--ct-color-font: #cdd1e0;
|
||||
}
|
||||
|
||||
.ct {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
transition: opacity 50ms ease-in, transform 70ms cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
will-change: opacity, top, left;
|
||||
box-shadow: 0 8px 12px 0 rgba(29, 32, 43, 0.17), 0 4px 5px -3px rgba(5, 6, 12, 0.49);
|
||||
border-radius: 9px;
|
||||
}
|
||||
|
||||
.ct::before {
|
||||
content: '';
|
||||
inset: 0;
|
||||
position: absolute;
|
||||
background-color: var(--ct-color-bg);
|
||||
z-index: -1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@supports (-webkit-mask-box-image: url('')) {
|
||||
.ct::before {
|
||||
border-radius: 0;
|
||||
-webkit-mask-box-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M10.71 0h2.58c3.02 0 4.64.42 6.1 1.2a8.18 8.18 0 013.4 3.4C23.6 6.07 24 7.7 24 10.71v2.58c0 3.02-.42 4.64-1.2 6.1a8.18 8.18 0 01-3.4 3.4c-1.47.8-3.1 1.21-6.11 1.21H10.7c-3.02 0-4.64-.42-6.1-1.2a8.18 8.18 0 01-3.4-3.4C.4 17.93 0 16.3 0 13.29V10.7c0-3.02.42-4.64 1.2-6.1a8.18 8.18 0 013.4-3.4C6.07.4 7.7 0 10.71 0z" fill="#000" fill-rule="nonzero"/></svg>') 48% 41% 37.9% 53.3%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.ct {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ct__content {
|
||||
padding: 6px 10px;
|
||||
color: var(--ct-color-font);
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
letter-spacing: 0.02em;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.ct::after {
|
||||
content: '';
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
background-color: var(--ct-color-bg);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.ct--bottom {
|
||||
transform: translateY(5px);
|
||||
}
|
||||
|
||||
.ct--bottom::after {
|
||||
top: -3px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) rotate(-45deg);
|
||||
}
|
||||
|
||||
.ct--top {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.ct--top::after {
|
||||
top: auto;
|
||||
bottom: -3px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) rotate(-45deg);
|
||||
}
|
||||
|
||||
.ct--left {
|
||||
transform: translateX(-5px);
|
||||
}
|
||||
|
||||
.ct--left::after {
|
||||
top: 50%;
|
||||
left: auto;
|
||||
right: 0;
|
||||
transform: translate(41.6%, -50%) rotate(-45deg);
|
||||
}
|
||||
|
||||
.ct--right {
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.ct--right::after {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
transform: translate(-41.6%, -50%) rotate(-45deg);
|
||||
}
|
||||
|
||||
.ct--shown {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
/**
|
||||
* CSS selector for the main editor wrapper element
|
||||
* Used in Cypress tests to query the editor container
|
||||
*/
|
||||
export const EDITOR_SELECTOR = '[data-interface=editorjs]';
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ import './commands';
|
|||
/**
|
||||
* Test constants
|
||||
*/
|
||||
export { EDITOR_SELECTOR } from './constants';
|
||||
export { EDITOR_INTERFACE_SELECTOR } from '../../../src/components/constants';
|
||||
|
||||
/**
|
||||
* File with custom assertions
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { ConversionConfig, ToolboxConfig, ToolConfig, API, BlockAPI } from
|
|||
import type { BlockTuneData } from '../../../../types/block-tunes/block-tune-data';
|
||||
import ToolMock, { type MockToolData } from '../../fixtures/tools/ToolMock';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
/**
|
||||
* There will be described test cases of 'blocks.*' API
|
||||
|
|
@ -74,7 +74,7 @@ describe('api.blocks', () => {
|
|||
|
||||
await editor.blocks.update(idToUpdate, newBlockData);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('[data-cy="block-wrapper"]')
|
||||
.should('have.text', newBlockData.text);
|
||||
});
|
||||
|
|
@ -213,7 +213,7 @@ describe('api.blocks', () => {
|
|||
expect(error.message).to.be.eq(`Block with id "${idToUpdate}" not found`);
|
||||
})
|
||||
.finally(() => {
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('[data-cy="block-wrapper"]')
|
||||
.invoke('text')
|
||||
.then(blockText => {
|
||||
|
|
@ -276,7 +276,7 @@ describe('api.blocks', () => {
|
|||
},
|
||||
], index)); // paste to the 0 index
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('[data-cy="block-wrapper"]')
|
||||
.each(($el, i) => {
|
||||
switch (i) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { createParagraphMock } from '../../support/utils/createParagraphMock';
|
||||
import type EditorJS from '../../../../types';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
/**
|
||||
* Test cases for Caret API
|
||||
|
|
@ -27,7 +27,7 @@ describe('Caret API', () => {
|
|||
/**
|
||||
* Blur caret from the block before setting via api
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.click();
|
||||
});
|
||||
it('should set caret to a block (and return true) if block index is passed as argument', () => {
|
||||
|
|
@ -47,7 +47,7 @@ describe('Caret API', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.first()
|
||||
.should(($block) => {
|
||||
|
|
@ -76,7 +76,7 @@ describe('Caret API', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.first()
|
||||
.should(($block) => {
|
||||
|
|
@ -110,7 +110,7 @@ describe('Caret API', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.first()
|
||||
.should(($block) => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* There will be described test cases of 'api.toolbar.*' API
|
||||
*/
|
||||
import type EditorJS from '../../../../types';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
describe('api.toolbar', () => {
|
||||
/**
|
||||
|
|
@ -36,7 +36,7 @@ describe('api.toolbar', () => {
|
|||
|
||||
describe('*.toggleToolbox()', () => {
|
||||
const isToolboxVisible = (): void => {
|
||||
cy.get(EDITOR_SELECTOR).find('div.ce-toolbox')
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR).find('div.ce-toolbox')
|
||||
.then((toolbox) => {
|
||||
if (toolbox.is(':visible')) {
|
||||
assert.isOk(true, 'Toolbox visible');
|
||||
|
|
@ -47,7 +47,7 @@ describe('api.toolbar', () => {
|
|||
};
|
||||
|
||||
const isToolboxNotVisible = (): void => {
|
||||
cy.get(EDITOR_SELECTOR).find('div.ce-toolbox')
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR).find('div.ce-toolbox')
|
||||
.then((toolbox) => {
|
||||
if (!toolbox.is(':visible')) {
|
||||
assert.isOk(true, 'Toolbox not visible');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ToolboxConfig, BlockToolData, ToolboxConfigEntry, PasteConfig } from '../../../../types';
|
||||
import type EditorJS from '../../../../types';
|
||||
import type { HTMLPasteEvent, TunesMenuConfig } from '../../../../types/tools';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
|
||||
|
|
@ -31,19 +31,19 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item[data-item-name=testTool]')
|
||||
.should('have.length', 1);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item[data-item-name=testTool] .ce-popover-item__icon')
|
||||
.should('contain.html', TestTool.toolbox.icon);
|
||||
});
|
||||
|
|
@ -76,24 +76,24 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item[data-item-name=testTool]')
|
||||
.should('have.length', 2);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item[data-item-name=testTool]')
|
||||
.first()
|
||||
.should('contain.text', (TestTool.toolbox as ToolboxConfigEntry[])[0].title);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item[data-item-name=testTool]')
|
||||
.last()
|
||||
.should('contain.text', (TestTool.toolbox as ToolboxConfigEntry[])[1].title);
|
||||
|
|
@ -165,19 +165,19 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item[data-item-name=testTool]')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.last()
|
||||
.click()
|
||||
|
|
@ -238,26 +238,26 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
// Insert test tool block
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get(`[data-item-name="testTool"]`)
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-name=testBlock]')
|
||||
.type('some text')
|
||||
.click();
|
||||
|
||||
// Open block tunes
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
|
|
@ -316,26 +316,26 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
// Insert test tool block
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get(`[data-item-name="testTool"]`)
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-name=testBlock]')
|
||||
.type('some text')
|
||||
.click();
|
||||
|
||||
// Open block tunes
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
|
|
@ -386,31 +386,31 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
// Insert test tool block
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get(`[data-item-name="testTool"]`)
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-name=testBlock]')
|
||||
.type('some text')
|
||||
.click();
|
||||
|
||||
// Open block tunes
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
// Expect preconfigured custom html tunes to exist in tunes menu
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover')
|
||||
.should('contain.text', sampleText);
|
||||
});
|
||||
|
|
@ -468,26 +468,26 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
// Insert test tool block
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get(`[data-item-name="testTool"]`)
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-name=testBlock]')
|
||||
.type('some text')
|
||||
.click();
|
||||
|
||||
// Open block tunes
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
|
|
@ -537,7 +537,7 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -594,7 +594,7 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -660,7 +660,7 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -746,7 +746,7 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -827,7 +827,7 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -918,7 +918,7 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -1001,7 +1001,7 @@ describe('Editor Tools Api', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { TunesMenuConfig } from '../../../../types/tools';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
|
||||
|
|
@ -32,12 +32,12 @@ describe('Editor Tunes Api', () => {
|
|||
tunes: [ 'testTune' ],
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.type('some text')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
|
|
@ -80,12 +80,12 @@ describe('Editor Tunes Api', () => {
|
|||
tunes: [ 'testTune' ],
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.type('some text')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
|
|
@ -121,16 +121,16 @@ describe('Editor Tunes Api', () => {
|
|||
tunes: [ 'testTune' ],
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.type('some text')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover')
|
||||
.should('contain.text', sampleText);
|
||||
});
|
||||
|
|
@ -173,12 +173,12 @@ describe('Editor Tunes Api', () => {
|
|||
tunes: [ 'testTune' ],
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.type('some text')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
|
|
@ -218,23 +218,23 @@ describe('Editor Tunes Api', () => {
|
|||
tunes: [ 'testTune' ],
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.type('some text')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Check test tune is inserted at index 0 */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-settings .ce-popover-item')
|
||||
.eq(0)
|
||||
.should('have.attr', 'data-item-name', 'test-tune' );
|
||||
|
||||
/** Check default Move Up tune is inserted below the test tune */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-settings .ce-popover-item')
|
||||
.eq(1)
|
||||
.should('have.attr', 'data-item-name', 'move-up' );
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import Header from '@editorjs/header';
|
||||
import { nanoid } from 'nanoid';
|
||||
import type EditorJS from '../../../types/index';
|
||||
import { EDITOR_SELECTOR } from '../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../src/components/constants';
|
||||
|
||||
|
||||
describe('Block ids', () => {
|
||||
|
|
@ -12,7 +12,7 @@ describe('Block ids', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('First block ')
|
||||
|
|
@ -22,15 +22,15 @@ describe('Block ids', () => {
|
|||
.type('Second block ')
|
||||
.type('{enter}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item[data-item-name=header]')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.last()
|
||||
.click()
|
||||
|
|
@ -108,7 +108,7 @@ describe('Block ids', () => {
|
|||
blocks,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -152,7 +152,7 @@ describe('Block ids', () => {
|
|||
blocks,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.each(($block, index) => {
|
||||
expect($block.attr('data-id')).to.eq(blocks[index].id);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import Header from '@editorjs/header';
|
|||
import Image from '@editorjs/simple-image';
|
||||
import * as _ from '../../../src/components/utils';
|
||||
import type { BlockTool, BlockToolData, OutputData } from '../../../types';
|
||||
import { EDITOR_SELECTOR } from '../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../src/components/constants';
|
||||
import $ from '../../../src/components/dom';
|
||||
import type EditorJS from '../../../types/index';
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
it('should paste plain text', () => {
|
||||
cy.createEditor({});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.as('block')
|
||||
.click()
|
||||
|
|
@ -27,7 +27,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
it('should paste inline html data', () => {
|
||||
cy.createEditor({});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.as('block')
|
||||
.click()
|
||||
|
|
@ -42,7 +42,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
it('should paste several blocks if plain text contains new lines', () => {
|
||||
cy.createEditor({});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -50,7 +50,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
'text/plain': 'First block\n\nSecond block',
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.then(blocks => {
|
||||
expect(blocks[0].textContent).to.eq('First block');
|
||||
|
|
@ -61,7 +61,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
it('should paste several blocks if html contains several paragraphs', () => {
|
||||
cy.createEditor({});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -69,7 +69,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
'text/html': '<p>First block</p><p>Second block</p>',
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.then(blocks => {
|
||||
expect(blocks[0].textContent).to.eq('First block');
|
||||
|
|
@ -80,7 +80,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
it('should paste using custom data type', () => {
|
||||
cy.createEditor({});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -101,7 +101,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
]),
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.then(blocks => {
|
||||
expect(blocks[0].textContent).to.eq('First block');
|
||||
|
|
@ -116,7 +116,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -127,11 +127,11 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
/**
|
||||
* Check inserted blocks
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('h2.ce-header')
|
||||
.should('contain', 'First block');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-paragraph')
|
||||
.should('contain', 'Second block');
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.paste({
|
||||
|
|
@ -173,7 +173,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
'text/plain': 'https://codex.so/public/app/img/external/codex2x.png',
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
// In Edge test are performed slower, so we need to increase timeout to wait until image is loaded on the page
|
||||
.get('img', { timeout: 10000 })
|
||||
.should('have.attr', 'src', 'https://codex.so/public/app/img/external/codex2x.png');
|
||||
|
|
@ -246,7 +246,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
it('should copy inline fragment', () => {
|
||||
cy.createEditor({});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('Some text{selectall}')
|
||||
|
|
@ -262,12 +262,12 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
it('should copy several blocks', () => {
|
||||
cy.createEditor({});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('First block{enter}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.next()
|
||||
.type('Second block')
|
||||
|
|
@ -302,7 +302,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
it('should cut inline fragment', () => {
|
||||
cy.createEditor({});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('Some text{selectall}')
|
||||
|
|
@ -331,7 +331,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.last()
|
||||
.click()
|
||||
|
|
@ -360,7 +360,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
});
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.should('not.contain', 'First block')
|
||||
.should('not.contain', 'Second block');
|
||||
});
|
||||
|
|
@ -384,7 +384,7 @@ describe.skip('Copy pasting from Editor', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.first()
|
||||
.click()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// eslint-disable-next-line spaced-comment, @typescript-eslint/triple-slash-reference
|
||||
/// <reference path="../support/index.d.ts" />
|
||||
import { EDITOR_SELECTOR } from '../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../src/components/constants';
|
||||
|
||||
describe('Editor basic initialization', () => {
|
||||
describe('Zero-config initialization', () => {
|
||||
|
|
@ -23,7 +23,7 @@ describe('Editor basic initialization', () => {
|
|||
/**
|
||||
* Assert if created instance is visible or not.
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.codex-editor')
|
||||
.should('be.visible');
|
||||
});
|
||||
|
|
@ -42,7 +42,7 @@ describe('Editor basic initialization', () => {
|
|||
readOnly: true,
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.codex-editor')
|
||||
.get('div.ce-paragraph')
|
||||
.invoke('attr', 'contenteditable')
|
||||
|
|
@ -59,7 +59,7 @@ describe('Editor basic initialization', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('#editor-js-styles')
|
||||
.should('have.attr', 'nonce', 'test-nonce');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { createEditorWithTextBlocks } from '../../../support/utils/createEditorWithTextBlocks';
|
||||
import ContentlessToolMock from '../../../fixtures/tools/ContentlessTool';
|
||||
import { EDITOR_SELECTOR } from '../../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../../src/components/constants';
|
||||
|
||||
describe('Arrow Left', () => {
|
||||
describe('starting whitespaces handling', () => {
|
||||
|
|
@ -10,7 +10,7 @@ describe('Arrow Left', () => {
|
|||
' 2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last() // select second block
|
||||
.click()
|
||||
|
|
@ -30,7 +30,7 @@ describe('Arrow Left', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -44,7 +44,7 @@ describe('Arrow Left', () => {
|
|||
' 2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last() // select second block
|
||||
.click()
|
||||
|
|
@ -63,7 +63,7 @@ describe('Arrow Left', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -78,7 +78,7 @@ describe('Arrow Left', () => {
|
|||
'<b></b>2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last() // select second block
|
||||
.click()
|
||||
|
|
@ -97,7 +97,7 @@ describe('Arrow Left', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -111,7 +111,7 @@ describe('Arrow Left', () => {
|
|||
'<b></b> 2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.click()
|
||||
|
|
@ -131,7 +131,7 @@ describe('Arrow Left', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -146,7 +146,7 @@ describe('Arrow Left', () => {
|
|||
'<b></b> 2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.click()
|
||||
|
|
@ -166,7 +166,7 @@ describe('Arrow Left', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -181,7 +181,7 @@ describe('Arrow Left', () => {
|
|||
' 2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.click()
|
||||
|
|
@ -201,7 +201,7 @@ describe('Arrow Left', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -256,7 +256,7 @@ describe('Arrow Left', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.as('thirdBlock')
|
||||
|
|
@ -267,7 +267,7 @@ describe('Arrow Left', () => {
|
|||
/**
|
||||
* We navigated to the Delimiter and it is highlighted
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div[data-cy-type=contentless-tool]')
|
||||
.parents('.ce-block')
|
||||
.as('delimiterBlock')
|
||||
|
|
@ -297,7 +297,7 @@ describe('Arrow Left', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.should(($block) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { createEditorWithTextBlocks } from '../../../support/utils/createEditorWithTextBlocks';
|
||||
import ContentlessToolMock from '../../../fixtures/tools/ContentlessTool';
|
||||
import { EDITOR_SELECTOR } from '../../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../../src/components/constants';
|
||||
|
||||
describe('Arrow Right', () => {
|
||||
describe('starting whitespaces handling', () => {
|
||||
|
|
@ -10,7 +10,7 @@ describe('Arrow Right', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first() // select first block
|
||||
.as('firstBlock')
|
||||
|
|
@ -32,7 +32,7 @@ describe('Arrow Right', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should(($block) => {
|
||||
|
|
@ -48,7 +48,7 @@ describe('Arrow Right', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -68,7 +68,7 @@ describe('Arrow Right', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should(($block) => {
|
||||
|
|
@ -84,7 +84,7 @@ describe('Arrow Right', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -104,7 +104,7 @@ describe('Arrow Right', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should(($block) => {
|
||||
|
|
@ -119,7 +119,7 @@ describe('Arrow Right', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -140,7 +140,7 @@ describe('Arrow Right', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should(($block) => {
|
||||
|
|
@ -156,7 +156,7 @@ describe('Arrow Right', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -177,7 +177,7 @@ describe('Arrow Right', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should(($block) => {
|
||||
|
|
@ -193,7 +193,7 @@ describe('Arrow Right', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -214,7 +214,7 @@ describe('Arrow Right', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should(($block) => {
|
||||
|
|
@ -270,7 +270,7 @@ describe('Arrow Right', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.as('firstBlock')
|
||||
|
|
@ -280,7 +280,7 @@ describe('Arrow Right', () => {
|
|||
/**
|
||||
* We navigated to the Delimiter and it is highlighted
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div[data-cy-type=contentless-tool]')
|
||||
.parents('.ce-block')
|
||||
.as('delimiterBlock')
|
||||
|
|
@ -310,7 +310,7 @@ describe('Arrow Right', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should(($block) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type EditorJS from '../../../../../types/index';
|
||||
import { createEditorWithTextBlocks } from '../../../support/utils/createEditorWithTextBlocks';
|
||||
import { EDITOR_SELECTOR } from '../../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../../src/components/constants';
|
||||
|
||||
describe('Delete keydown', () => {
|
||||
describe('ending whitespaces handling', () => {
|
||||
|
|
@ -10,7 +10,7 @@ describe('Delete keydown', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -27,7 +27,7 @@ describe('Delete keydown', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -35,7 +35,7 @@ describe('Delete keydown', () => {
|
|||
.type('{rightArrow}') // set caret after "1";
|
||||
.type('{del}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.last()
|
||||
.should('have.text', '1 2');
|
||||
|
|
@ -46,7 +46,7 @@ describe('Delete keydown', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -54,7 +54,7 @@ describe('Delete keydown', () => {
|
|||
.type('{rightArrow}') // set caret after "1";
|
||||
.type('{del}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.last()
|
||||
.should('have.text', '12');
|
||||
|
|
@ -65,7 +65,7 @@ describe('Delete keydown', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -74,7 +74,7 @@ describe('Delete keydown', () => {
|
|||
.type('{del}') // remove nbsp
|
||||
.type('{del}'); // ignore empty tag and merge
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.last()
|
||||
.should('have.text', '12');
|
||||
|
|
@ -86,7 +86,7 @@ describe('Delete keydown', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -95,7 +95,7 @@ describe('Delete keydown', () => {
|
|||
.type('{del}') // remove nbsp
|
||||
.type('{del}'); // ignore empty tag and merge
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.last()
|
||||
.should('have.text', '12');
|
||||
|
|
@ -107,7 +107,7 @@ describe('Delete keydown', () => {
|
|||
'2',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -116,7 +116,7 @@ describe('Delete keydown', () => {
|
|||
.type('{del}') // remove nbsp
|
||||
.type('{del}'); // ignore regular space and merge
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.last()
|
||||
/**
|
||||
|
|
@ -141,14 +141,14 @@ describe('Delete keydown', () => {
|
|||
'The second block',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
.selectText('The ')
|
||||
.type('{del}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.first()
|
||||
.should('have.text', 'first block');
|
||||
|
|
@ -160,14 +160,14 @@ describe('Delete keydown', () => {
|
|||
'The second block',
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click() // caret will be at the end of the block
|
||||
.type('{leftarrow}') // now caret is not at the end
|
||||
.type('{del}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.first()
|
||||
.should('have.text', 'The first bloc'); // last char is removed
|
||||
|
|
@ -217,14 +217,14 @@ describe('Delete keydown', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('[data-cy=quote-tool]')
|
||||
.find('div[contenteditable]')
|
||||
.first()
|
||||
.click()
|
||||
.type('{del}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('[data-cy=quote-tool]')
|
||||
.find('div[contenteditable]')
|
||||
.last()
|
||||
|
|
@ -267,7 +267,7 @@ describe('Delete keydown', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -304,7 +304,7 @@ describe('Delete keydown', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -334,7 +334,7 @@ describe('Delete keydown', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -345,7 +345,7 @@ describe('Delete keydown', () => {
|
|||
/**
|
||||
* Toolbox has been closed
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-toolbar')
|
||||
.should('not.have.class', 'ce-toolbar--opened');
|
||||
});
|
||||
|
|
@ -372,7 +372,7 @@ describe('Delete keydown', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -402,7 +402,7 @@ describe('Delete keydown', () => {
|
|||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -414,7 +414,7 @@ describe('Delete keydown', () => {
|
|||
/**
|
||||
* Toolbox has been closed
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-toolbar')
|
||||
.should('not.have.class', 'ce-toolbar--opened');
|
||||
});
|
||||
|
|
@ -464,12 +464,12 @@ describe('Delete keydown', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('{del}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('[data-cy=unmergeable-tool]')
|
||||
.as('secondBlock');
|
||||
|
||||
|
|
@ -495,12 +495,12 @@ describe('Delete keydown', () => {
|
|||
it('should do nothing', () => {
|
||||
createEditorWithTextBlocks([ 'The only block. Not empty' ]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('{del}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.should('have.length', 1)
|
||||
.should('have.text', 'The only block. Not empty');
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EDITOR_SELECTOR } from '../../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../../src/components/constants';
|
||||
|
||||
describe('Enter keydown', () => {
|
||||
it('should split block and remove selected fragment if some text fragment selected', () => {
|
||||
|
|
@ -15,14 +15,14 @@ describe('Enter keydown', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.selectText('with so')
|
||||
.wait(0)
|
||||
.type('{enter}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.then((blocks) => {
|
||||
/**
|
||||
|
|
@ -52,12 +52,12 @@ describe('Enter keydown', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('{enter}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.last()
|
||||
.as('lastBlock');
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EDITOR_SELECTOR } from '../../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../../src/components/constants';
|
||||
|
||||
describe('Slash keydown', () => {
|
||||
describe('pressed in empty block', () => {
|
||||
|
|
@ -16,7 +16,7 @@ describe('Slash keydown', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('/');
|
||||
|
|
@ -24,7 +24,7 @@ describe('Slash keydown', () => {
|
|||
/**
|
||||
* Block content should contain slash
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.invoke('text')
|
||||
.should('eq', '/');
|
||||
|
|
@ -51,7 +51,7 @@ describe('Slash keydown', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type(`{${key}}/`);
|
||||
|
|
@ -77,7 +77,7 @@ describe('Slash keydown', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('/');
|
||||
|
|
@ -88,7 +88,7 @@ describe('Slash keydown', () => {
|
|||
/**
|
||||
* Block content should contain slash
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.invoke('text')
|
||||
.should('eq', 'Hello/');
|
||||
|
|
@ -120,10 +120,10 @@ describe('Slash keydown', () => {
|
|||
|
||||
// Step 1
|
||||
// Click on the plus button and select the text option
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click();
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-toolbar__plus')
|
||||
.click({ force: true });
|
||||
cy.get('[data-cy="toolbox"] .ce-popover__container')
|
||||
|
|
@ -165,7 +165,7 @@ describe('CMD+Slash keydown', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('{cmd}/');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import Header from '@editorjs/header';
|
||||
import NestedEditor, { NESTED_EDITOR_ID } from '../../support/utils/nestedEditorInstance';
|
||||
import type { MenuConfig, ToolConstructable } from '@/types/tools';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
describe('Inline Toolbar', () => {
|
||||
it('should appear aligned with left coord of selection rect', () => {
|
||||
|
|
@ -18,7 +18,7 @@ describe('Inline Toolbar', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.selectText('block');
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ describe('Inline Toolbar', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.as('blockWrapper')
|
||||
.getLineWrapPositions()
|
||||
|
|
@ -68,7 +68,7 @@ describe('Inline Toolbar', () => {
|
|||
/**
|
||||
* Select last 5 chars of the first line
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.selectTextByOffset([firstLineWrapIndex - 5, firstLineWrapIndex - 1]);
|
||||
});
|
||||
|
|
@ -136,11 +136,11 @@ describe('Inline Toolbar', () => {
|
|||
});
|
||||
|
||||
/** Open Inline Toolbar */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-header')
|
||||
.selectText('block');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-cy=inline-toolbar]')
|
||||
.get('.ce-popover--opened')
|
||||
.as('toolbar')
|
||||
|
|
@ -183,7 +183,7 @@ describe('Inline Toolbar', () => {
|
|||
|
||||
form.appendChild(editorElement);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.selectText('Some text');
|
||||
|
||||
|
|
@ -214,19 +214,19 @@ describe('Inline Toolbar', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.selectText('Some text');
|
||||
|
||||
cy.get('[data-item-name=convert-to]')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-inline-toolbar')
|
||||
.find('.ce-popover-item[data-item-name=header]')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-header')
|
||||
.should('have.text', 'Some text');
|
||||
|
||||
|
|
@ -242,7 +242,7 @@ describe('Inline Toolbar', () => {
|
|||
throw new Error('No range available');
|
||||
}
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-header')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import ToolMock, { type MockToolData } from '../../fixtures/tools/ToolMock';
|
||||
import type EditorJS from '../../../../types/index';
|
||||
import type { BlockToolConstructorOptions } from '../../../../types';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
describe('Renderer module', () => {
|
||||
it('should not cause onChange firing during initial rendering', () => {
|
||||
|
|
@ -59,11 +59,11 @@ describe('Renderer module', () => {
|
|||
})
|
||||
.as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.should('have.length', 3);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.each(($el, index) => {
|
||||
/**
|
||||
|
|
@ -125,11 +125,11 @@ describe('Renderer module', () => {
|
|||
})
|
||||
.as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.should('have.length', 3);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.each(($el, index) => {
|
||||
/**
|
||||
|
|
@ -158,7 +158,7 @@ describe('Renderer module', () => {
|
|||
})
|
||||
.as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.should('have.length', 1);
|
||||
});
|
||||
|
|
@ -174,7 +174,7 @@ describe('Renderer module', () => {
|
|||
});
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.should('have.length', 1);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type EditorJS from '../../../../types/index';
|
||||
import Header from '@editorjs/header';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
describe('Saver module', () => {
|
||||
describe('save()', () => {
|
||||
|
|
@ -22,7 +22,7 @@ describe('Saver module', () => {
|
|||
*/
|
||||
const extensionNode = document.createElement('extension-node');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block__content')
|
||||
.then((blockContent) => {
|
||||
blockContent.append(extensionNode);
|
||||
|
|
@ -58,18 +58,18 @@ describe('Saver module', () => {
|
|||
})
|
||||
.as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('span.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/**
|
||||
* Change header level
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-settings .ce-popover-item:nth-child(3)')
|
||||
.click();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { createEditorWithTextBlocks } from '../../support/utils/createEditorWithTextBlocks';
|
||||
import type EditorJS from '../../../../types/index';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
describe('Ui module', () => {
|
||||
describe('documentKeydown', () => {
|
||||
|
|
@ -30,7 +30,7 @@ describe('Ui module', () => {
|
|||
/**
|
||||
* Select two blocks by shift+down
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -76,7 +76,7 @@ describe('Ui module', () => {
|
|||
/**
|
||||
* Select two blocks by shift+down
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.click()
|
||||
|
|
@ -105,7 +105,7 @@ describe('Ui module', () => {
|
|||
])
|
||||
.as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.eq(1)
|
||||
.click();
|
||||
|
|
@ -128,7 +128,7 @@ describe('Ui module', () => {
|
|||
})
|
||||
.as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.eq(1)
|
||||
.click();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import Header from '@editorjs/header';
|
|||
import Code from '@editorjs/code';
|
||||
import ToolMock from '../fixtures/tools/ToolMock';
|
||||
import Delimiter from '@editorjs/delimiter';
|
||||
import { EDITOR_SELECTOR } from '../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../src/components/constants';
|
||||
import { BlockAddedMutationType } from '../../../types/events/block/BlockAdded';
|
||||
import { BlockChangedMutationType } from '../../../types/events/block/BlockChanged';
|
||||
import { BlockRemovedMutationType } from '../../../types/events/block/BlockRemoved';
|
||||
|
|
@ -82,7 +82,7 @@ describe('onChange callback', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('change')
|
||||
|
|
@ -114,7 +114,7 @@ describe('onChange callback', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('first change')
|
||||
|
|
@ -137,7 +137,7 @@ describe('onChange callback', () => {
|
|||
it('should be fired with correct index on block insertion above the current (by pressing Enter at the start)', () => {
|
||||
createEditor();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('{enter}');
|
||||
|
|
@ -161,7 +161,7 @@ describe('onChange callback', () => {
|
|||
},
|
||||
} ]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('{enter}');
|
||||
|
|
@ -180,7 +180,7 @@ describe('onChange callback', () => {
|
|||
},
|
||||
} ]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('{enter}');
|
||||
|
|
@ -196,7 +196,7 @@ describe('onChange callback', () => {
|
|||
it('should be fired on typing into block', () => {
|
||||
createEditor();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('some text');
|
||||
|
|
@ -212,15 +212,15 @@ describe('onChange callback', () => {
|
|||
it('should be fired on block insertion with save inside onChange', () => {
|
||||
createEditorWithSave();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item[data-item-name=delimiter]')
|
||||
.click();
|
||||
|
||||
|
|
@ -258,15 +258,15 @@ describe('onChange callback', () => {
|
|||
it('should be fired on block replacement for both of blocks', () => {
|
||||
createEditor();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-toolbar__plus')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item[data-item-name=header]')
|
||||
.click();
|
||||
|
||||
|
|
@ -302,15 +302,15 @@ describe('onChange callback', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('span.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-settings .ce-popover-item:nth-child(4)')
|
||||
.click();
|
||||
|
||||
|
|
@ -335,20 +335,20 @@ describe('onChange callback', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('span.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name=delete]')
|
||||
.click();
|
||||
|
||||
/** Second click for confirmation */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name=delete]')
|
||||
.click();
|
||||
|
||||
|
|
@ -390,16 +390,16 @@ describe('onChange callback', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.last()
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('span.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name=move-up]')
|
||||
.click();
|
||||
|
||||
|
|
@ -420,7 +420,7 @@ describe('onChange callback', () => {
|
|||
},
|
||||
} ]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('textarea')
|
||||
.type('Some input to the textarea');
|
||||
|
||||
|
|
@ -440,21 +440,21 @@ describe('onChange callback', () => {
|
|||
},
|
||||
} ]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
/**
|
||||
* Open Block Tunes, add fake cursor
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('span.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/**
|
||||
* Close Block Tunes, remove fake cursor
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click();
|
||||
|
||||
|
|
@ -471,7 +471,7 @@ describe('onChange callback', () => {
|
|||
},
|
||||
} ]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('div.ce-block')
|
||||
.click()
|
||||
.type('{backspace}');
|
||||
|
|
@ -673,7 +673,7 @@ describe('onChange callback', () => {
|
|||
/**
|
||||
* Emulate tool's child-element text typing
|
||||
*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-cy=tool-child]')
|
||||
.click()
|
||||
.type('some text');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import * as _ from '../../../src/components/utils';
|
||||
import { EDITOR_SELECTOR } from '../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../src/components/constants';
|
||||
|
||||
describe('Blocks selection', () => {
|
||||
beforeEach(() => {
|
||||
|
|
@ -13,12 +13,12 @@ describe('Blocks selection', () => {
|
|||
});
|
||||
|
||||
it('should remove block selection on click', () => {
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.click()
|
||||
.type('First block{enter}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('div.ce-block')
|
||||
.next()
|
||||
.type('Second block')
|
||||
|
|
@ -28,7 +28,7 @@ describe('Blocks selection', () => {
|
|||
keyCode: _.keyCodes.UP,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.click()
|
||||
.find('div.ce-block')
|
||||
.should('not.have.class', '.ce-block--selected');
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Header from '@editorjs/header';
|
|||
import type { ConversionConfig, ToolboxConfig } from '../../../../types';
|
||||
import type { MenuConfig } from '../../../../types/tools';
|
||||
import { ToolWithoutConversionExport } from '../../fixtures/tools/ToolWithoutConversionExport';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
describe('BlockTunes', () => {
|
||||
describe('Keyboard only', () => {
|
||||
|
|
@ -23,7 +23,7 @@ describe('BlockTunes', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('{cmd}/')
|
||||
|
|
@ -53,7 +53,7 @@ describe('BlockTunes', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('{cmd}/')
|
||||
|
|
@ -88,28 +88,28 @@ describe('BlockTunes', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Check "Convert to" option is present */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item')
|
||||
.contains('Convert to')
|
||||
.should('exist');
|
||||
|
||||
/** Click "Convert to" option*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item')
|
||||
.contains('Convert to')
|
||||
.click();
|
||||
|
||||
/** Check connected popover with the "Heading" option is present */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover--nested [data-item-name=header]')
|
||||
.should('exist');
|
||||
});
|
||||
|
|
@ -130,16 +130,16 @@ describe('BlockTunes', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Check "Convert to" option is not present */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item')
|
||||
.contains('Convert to')
|
||||
.should('not.exist');
|
||||
|
|
@ -163,17 +163,17 @@ describe('BlockTunes', () => {
|
|||
}).as('editorInstance');
|
||||
|
||||
cy.get('@editorInstance')
|
||||
.get(EDITOR_SELECTOR)
|
||||
.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get('@editorInstance')
|
||||
.get(EDITOR_SELECTOR)
|
||||
.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
cy.get('@editorInstance')
|
||||
.get(EDITOR_SELECTOR)
|
||||
.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-popover-item[data-item-name=convert-to]')
|
||||
.should('not.exist');
|
||||
});
|
||||
|
|
@ -256,28 +256,28 @@ describe('BlockTunes', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Open "Convert to" menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item')
|
||||
.contains('Convert to')
|
||||
.click();
|
||||
|
||||
/** Check TestTool option with SAME data is NOT present */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover--nested [data-item-name=testTool]')
|
||||
.contains('Title 1')
|
||||
.should('not.exist');
|
||||
|
||||
/** Check TestTool option with DIFFERENT data IS present */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover--nested [data-item-name=testTool]')
|
||||
.contains('Title 2')
|
||||
.should('exist');
|
||||
|
|
@ -301,27 +301,27 @@ describe('BlockTunes', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Click "Convert to" option*/
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item')
|
||||
.contains('Convert to')
|
||||
.click();
|
||||
|
||||
/** Click "Heading" option */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover--nested [data-item-name=header]')
|
||||
.click();
|
||||
|
||||
/** Check the block was converted to the second option */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-header')
|
||||
.should('have.text', 'Some text');
|
||||
|
||||
|
|
@ -335,7 +335,7 @@ describe('BlockTunes', () => {
|
|||
throw new Error('Range is undefined');
|
||||
}
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-header')
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -418,21 +418,21 @@ describe('BlockTunes', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Check there are more than 1 tune */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item')
|
||||
.should('have.length.above', 1);
|
||||
|
||||
/** Check the first tune is tool specific tune */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-item:first-child')
|
||||
.contains('Tune')
|
||||
.should('exist');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { createEditorWithTextBlocks } from '../../support/utils/createEditorWithTextBlocks';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
describe('inputs [data-empty] mark', () => {
|
||||
it('should be added to inputs of editor on initialization', () => {
|
||||
|
|
@ -8,12 +8,12 @@ describe('inputs [data-empty] mark', () => {
|
|||
'', // empty block
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.first()
|
||||
.should('have.attr', 'data-empty', 'false');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should('have.attr', 'data-empty', 'true');
|
||||
|
|
@ -25,12 +25,12 @@ describe('inputs [data-empty] mark', () => {
|
|||
'', // empty block
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.type('Some text');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should('have.attr', 'data-empty', 'false');
|
||||
|
|
@ -42,12 +42,12 @@ describe('inputs [data-empty] mark', () => {
|
|||
'Some text', // not empty block
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.type('{selectall}{backspace}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should('have.attr', 'data-empty', 'true');
|
||||
|
|
@ -59,12 +59,12 @@ describe('inputs [data-empty] mark', () => {
|
|||
'', // empty block
|
||||
]);
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.type('{enter}');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.last()
|
||||
.should('have.attr', 'data-empty', 'true');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import Header from '@editorjs/header';
|
||||
import type { InlineTool, InlineToolConstructorOptions, MenuConfig, ToolConstructable } from '../../../../types/tools';
|
||||
import { createEditorWithTextBlocks } from '../../support/utils/createEditorWithTextBlocks';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
describe('Inline Toolbar', () => {
|
||||
describe('Separators', () => {
|
||||
|
|
@ -25,18 +25,18 @@ describe('Inline Toolbar', () => {
|
|||
});
|
||||
|
||||
/** Open Inline Toolbar */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.selectText('block');
|
||||
|
||||
/** Check that first item (which is convert-to and has children) has a separator after it */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-cy=inline-toolbar] .ce-popover__items')
|
||||
.children()
|
||||
.first()
|
||||
.should('have.attr', 'data-item-name', 'convert-to');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-cy=inline-toolbar] .ce-popover__items')
|
||||
.children()
|
||||
.eq(1)
|
||||
|
|
@ -92,24 +92,24 @@ describe('Inline Toolbar', () => {
|
|||
});
|
||||
|
||||
/** Open Inline Toolbar */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-header')
|
||||
.selectText('block');
|
||||
|
||||
/** Check that item with children is surrounded by separators */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-cy=inline-toolbar] .ce-popover__items')
|
||||
.children()
|
||||
.eq(3)
|
||||
.should('have.class', 'ce-popover-item-separator');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-cy=inline-toolbar] .ce-popover__items')
|
||||
.children()
|
||||
.eq(4)
|
||||
.should('have.attr', 'data-item-name', 'test-tool');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-cy=inline-toolbar] .ce-popover__items')
|
||||
.children()
|
||||
.eq(5)
|
||||
|
|
@ -165,18 +165,18 @@ describe('Inline Toolbar', () => {
|
|||
});
|
||||
|
||||
/** Open Inline Toolbar */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-header')
|
||||
.selectText('block');
|
||||
|
||||
/** Check that item with children is surrounded by separators */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-cy=inline-toolbar] .ce-popover__items')
|
||||
.children()
|
||||
.eq(3)
|
||||
.should('have.class', 'ce-popover-item-separator');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-cy=inline-toolbar] .ce-popover__items')
|
||||
.children()
|
||||
.eq(4)
|
||||
|
|
@ -214,7 +214,7 @@ describe('Inline Toolbar', () => {
|
|||
readOnly: true,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.selectText('text');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
/**
|
||||
* Text will be passed as a placeholder to the editor
|
||||
|
|
@ -19,7 +19,7 @@ describe('Placeholders', () => {
|
|||
placeholder: PLACEHOLDER_TEXT,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.getPseudoElementContent('::before')
|
||||
.should('eq', PLACEHOLDER_TEXT);
|
||||
|
|
@ -31,7 +31,7 @@ describe('Placeholders', () => {
|
|||
autofocus: true,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.getPseudoElementContent('::before')
|
||||
.should('eq', PLACEHOLDER_TEXT);
|
||||
|
|
@ -42,7 +42,7 @@ describe('Placeholders', () => {
|
|||
placeholder: PLACEHOLDER_TEXT,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.as('firstBlock')
|
||||
|
|
@ -55,7 +55,7 @@ describe('Placeholders', () => {
|
|||
placeholder: PLACEHOLDER_TEXT,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.type('aaa')
|
||||
.type('{selectall}{backspace}')
|
||||
|
|
@ -68,7 +68,7 @@ describe('Placeholders', () => {
|
|||
placeholder: PLACEHOLDER_TEXT,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.as('firstBlock')
|
||||
.getPseudoElementContent('::before')
|
||||
|
|
@ -85,7 +85,7 @@ describe('Placeholders', () => {
|
|||
placeholder: PLACEHOLDER_TEXT,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.as('firstBlock')
|
||||
.getPseudoElementContent('::before')
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type EditorJS from '../../../../types/index';
|
||||
import type { ConversionConfig, ToolboxConfig } from '../../../../types/index';
|
||||
import ToolMock from '../../fixtures/tools/ToolMock';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
describe('Toolbox', () => {
|
||||
describe('Shortcuts', () => {
|
||||
|
|
@ -39,7 +39,7 @@ describe('Toolbox', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('Some text')
|
||||
|
|
@ -68,7 +68,7 @@ describe('Toolbox', () => {
|
|||
throw new Error('Selection range is not available');
|
||||
}
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find(`.ce-block[data-id=${blocks[0].id}]`)
|
||||
.should(($block) => {
|
||||
expect($block[0].contains(range.startContainer)).to.be.true;
|
||||
|
|
@ -102,7 +102,7 @@ describe('Toolbox', () => {
|
|||
},
|
||||
}).as('editorInstance');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('Some text')
|
||||
|
|
@ -151,7 +151,7 @@ describe('Toolbox', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('Some text')
|
||||
|
|
@ -203,7 +203,7 @@ describe('Toolbox', () => {
|
|||
},
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.click()
|
||||
.type('Some text')
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { PopoverItemParams } from '../../../../types/index.js';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
/**
|
||||
* Mock of some Block Tool
|
||||
|
|
@ -70,7 +70,7 @@ describe('Flipper', () => {
|
|||
|
||||
cy.spy(SomePlugin, 'pluginInternalKeydownHandler');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-some-plugin')
|
||||
.as('pluginInput')
|
||||
.focus()
|
||||
|
|
@ -78,7 +78,7 @@ describe('Flipper', () => {
|
|||
.wait(100);
|
||||
|
||||
// Try to delete the block via keyboard
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-some-plugin')
|
||||
// Open tunes menu
|
||||
.trigger('keydown', { code: 'Slash',
|
||||
|
|
@ -93,7 +93,7 @@ describe('Flipper', () => {
|
|||
cy.get('[data-item-name="delete"]')
|
||||
.should('have.class', 'ce-popover-item--focused');
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-some-plugin')
|
||||
// Click delete
|
||||
.trigger('keydown', { keyCode: ENTER_KEY_CODE })
|
||||
|
|
@ -118,7 +118,7 @@ describe('Flipper', () => {
|
|||
autofocus: true,
|
||||
});
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-paragraph')
|
||||
.as('paragraph')
|
||||
.selectTextByOffset([0, 10])
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { PopoverDesktop as Popover, PopoverItemType } from '../../../../src/comp
|
|||
import type { PopoverItemParams } from '@/types/utils/popover';
|
||||
import type { MenuConfig } from '../../../../types/tools';
|
||||
import type { BlockToolConstructable } from '../../../../types/tools';
|
||||
import { EDITOR_SELECTOR } from '../../support/constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
import Header from '@editorjs/header';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
|
|
@ -285,16 +285,16 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Check item with custom html content is displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover .ce-popover-item-html')
|
||||
.contains('Tune')
|
||||
.should('be.visible');
|
||||
|
|
@ -355,11 +355,11 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
|
|
@ -368,7 +368,7 @@ describe('Popover', () => {
|
|||
cy.get('body').tab();
|
||||
|
||||
/** Check the first custom html item is focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover .ce-popover-item-html .ce-settings__button')
|
||||
.contains('Tune1')
|
||||
.should('have.class', 'ce-popover-item--focused');
|
||||
|
|
@ -378,7 +378,7 @@ describe('Popover', () => {
|
|||
cy.get('body').tab();
|
||||
|
||||
/** Check the second custom html item is focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover .ce-popover-item-html .ce-settings__button')
|
||||
.contains('Tune2')
|
||||
.should('have.class', 'ce-popover-item--focused');
|
||||
|
|
@ -388,7 +388,7 @@ describe('Popover', () => {
|
|||
cy.get('body').tab();
|
||||
|
||||
/** Check that default popover item got focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name=move-up]')
|
||||
.should('have.class', 'ce-popover-item--focused');
|
||||
});
|
||||
|
|
@ -438,32 +438,32 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Check item with children has arrow icon */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name="test-item"]')
|
||||
.get('.ce-popover-item__icon--chevron-right')
|
||||
.should('be.visible');
|
||||
|
||||
/** Click the item */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name="test-item"]')
|
||||
.click();
|
||||
|
||||
/** Check nested popover opened */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover--nested .ce-popover__container')
|
||||
.should('be.visible');
|
||||
|
||||
/** Check child item displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover--nested .ce-popover__container')
|
||||
.get('[data-item-name="nested-test-item"]')
|
||||
.should('be.visible');
|
||||
|
|
@ -517,62 +517,62 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Check item with children has arrow icon */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name="test-item"]')
|
||||
.get('.ce-popover-item__icon--chevron-right')
|
||||
.should('be.visible');
|
||||
|
||||
/** Click the item */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name="test-item"]')
|
||||
.click();
|
||||
|
||||
/** Check child item displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="nested-test-item"]')
|
||||
.should('be.visible');
|
||||
|
||||
/** Check header displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-header')
|
||||
.should('have.text', 'Tune');
|
||||
|
||||
/** Check back button displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('.ce-popover-header__back-button')
|
||||
.should('be.visible');
|
||||
|
||||
/** Click back button */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('.ce-popover-header__back-button')
|
||||
.click();
|
||||
|
||||
/** Check child item is not displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="nested-test-item"]')
|
||||
.should('not.exist');
|
||||
|
||||
/** Check back button is not displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('.ce-popover-header__back-button')
|
||||
.should('not.exist');
|
||||
|
||||
/** Check header is not displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover-header')
|
||||
.should('not.exist');
|
||||
});
|
||||
|
|
@ -614,16 +614,16 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Check item displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="test-item"]')
|
||||
.should('be.visible');
|
||||
|
|
@ -671,22 +671,22 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
/** Check item displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="test-item"]')
|
||||
.should('be.visible');
|
||||
|
||||
/** Check separator displayed */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('.ce-popover-item-separator')
|
||||
.should('be.visible');
|
||||
|
|
@ -738,11 +738,11 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open block tunes menu */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.cdx-block')
|
||||
.click();
|
||||
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-toolbar__settings-btn')
|
||||
.click();
|
||||
|
||||
|
|
@ -751,13 +751,13 @@ describe('Popover', () => {
|
|||
cy.get('body').tab();
|
||||
|
||||
/** Check first item is focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="test-item-1"].ce-popover-item--focused')
|
||||
.should('exist');
|
||||
|
||||
/** Check second item is not focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="test-item-2"].ce-popover-item--focused')
|
||||
.should('not.exist');
|
||||
|
|
@ -767,13 +767,13 @@ describe('Popover', () => {
|
|||
cy.get('body').tab();
|
||||
|
||||
/** Check first item is not focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="test-item-1"].ce-popover-item--focused')
|
||||
.should('not.exist');
|
||||
|
||||
/** Check second item is focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="test-item-2"].ce-popover-item--focused')
|
||||
.should('exist');
|
||||
|
|
@ -801,27 +801,27 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open Inline Toolbar */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.selectText('block');
|
||||
|
||||
/** Hover Convert To item which has nested popover */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name=convert-to]')
|
||||
.trigger('mouseover');
|
||||
|
||||
/** Check nested popover didn't open */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover--nested .ce-popover__container')
|
||||
.should('not.exist');
|
||||
|
||||
/** Click Convert To item which has nested popover */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('[data-item-name=convert-to]')
|
||||
.click();
|
||||
|
||||
/** Check nested popover opened */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover--nested .ce-popover__container')
|
||||
.should('exist');
|
||||
});
|
||||
|
|
@ -847,17 +847,17 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open Inline Toolbar */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.selectText('block');
|
||||
|
||||
/** Check Inline Popover opened */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-inline-toolbar .ce-popover__container')
|
||||
.should('be.visible');
|
||||
|
||||
/** Check first item is NOT focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-inline-toolbar .ce-popover__container')
|
||||
.get('[data-item-name="convert-to"].ce-popover-item--focused')
|
||||
.should('not.exist');
|
||||
|
|
@ -866,13 +866,13 @@ describe('Popover', () => {
|
|||
cy.tab();
|
||||
|
||||
/** Check first item became focused after tab */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-inline-toolbar .ce-popover__container')
|
||||
.get('[data-item-name="convert-to"].ce-popover-item--focused')
|
||||
.should('exist');
|
||||
|
||||
/** Check second item is NOT focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-inline-toolbar .ce-popover__container')
|
||||
.get('[data-item-name="link"] .ce-popover-item--focused')
|
||||
.should('not.exist');
|
||||
|
|
@ -881,7 +881,7 @@ describe('Popover', () => {
|
|||
cy.tab();
|
||||
|
||||
/** Check second item became focused after tab */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-inline-toolbar .ce-popover__container')
|
||||
.get('[data-item-name="link"] .ce-popover-item--focused')
|
||||
.should('exist');
|
||||
|
|
@ -908,12 +908,12 @@ describe('Popover', () => {
|
|||
});
|
||||
|
||||
/** Open Inline Toolbar */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.find('.ce-paragraph')
|
||||
.selectText('block');
|
||||
|
||||
/** Check Inline Popover opened */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-inline-toolbar .ce-popover__container')
|
||||
.should('be.visible');
|
||||
|
||||
|
|
@ -925,12 +925,12 @@ describe('Popover', () => {
|
|||
.type('{enter}');
|
||||
|
||||
/** Check Inline Popover opened */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-inline-toolbar .ce-popover--nested .ce-popover__container')
|
||||
.should('be.visible');
|
||||
|
||||
/** Check first item is NOT focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="header"].ce-popover-item--focused')
|
||||
.should('not.exist');
|
||||
|
|
@ -940,7 +940,7 @@ describe('Popover', () => {
|
|||
cy.get('body').tab();
|
||||
|
||||
/** Check first item is focused */
|
||||
cy.get(EDITOR_SELECTOR)
|
||||
cy.get(EDITOR_INTERFACE_SELECTOR)
|
||||
.get('.ce-popover__container')
|
||||
.get('[data-item-name="header"].ce-popover-item--focused')
|
||||
.should('exist');
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
/**
|
||||
* CSS selector for the main editor wrapper element
|
||||
* Used in Playwright tests to query the editor container
|
||||
*/
|
||||
export const EDITOR_SELECTOR = '[data-interface=editorjs]';
|
||||
|
||||
|
|
@ -4,20 +4,19 @@ import path from 'node:path';
|
|||
import { pathToFileURL } from 'node:url';
|
||||
import type { OutputData } from '@/types';
|
||||
import { ensureEditorBundleBuilt } from './helpers/ensure-build';
|
||||
import { EDITOR_SELECTOR } from './constants';
|
||||
import { TOOLTIP_INTERFACE_SELECTOR, EDITOR_INTERFACE_SELECTOR, INLINE_TOOLBAR_INTERFACE_SELECTOR } from '../../../src/components/constants';
|
||||
|
||||
const TEST_PAGE_URL = pathToFileURL(
|
||||
path.resolve(__dirname, '../../cypress/fixtures/test.html')
|
||||
).href;
|
||||
|
||||
const HOLDER_ID = 'editorjs';
|
||||
const BLOCK_SELECTOR = `${EDITOR_SELECTOR} div.ce-block`;
|
||||
const PARAGRAPH_SELECTOR = `${EDITOR_SELECTOR} [data-block-tool="paragraph"]`;
|
||||
const SETTINGS_BUTTON_SELECTOR = `${EDITOR_SELECTOR} .ce-toolbar__settings-btn`;
|
||||
const PLUS_BUTTON_SELECTOR = `${EDITOR_SELECTOR} .ce-toolbar__plus`;
|
||||
const INLINE_TOOLBAR_SELECTOR = `${EDITOR_SELECTOR} [data-interface=inline-toolbar]`;
|
||||
const POPOVER_SELECTOR = `${EDITOR_SELECTOR} .ce-popover`;
|
||||
const TOOLTIP_SELECTOR = '.ct';
|
||||
const BLOCK_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} div.ce-block`;
|
||||
const PARAGRAPH_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} [data-block-tool="paragraph"]`;
|
||||
const SETTINGS_BUTTON_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} .ce-toolbar__settings-btn`;
|
||||
const PLUS_BUTTON_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} .ce-toolbar__plus`;
|
||||
const INLINE_TOOLBAR_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} ${INLINE_TOOLBAR_INTERFACE_SELECTOR}`;
|
||||
const POPOVER_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} .ce-popover`;
|
||||
const LINK_TOOL_SHORTCUT_MODIFIER = process.platform === 'darwin' ? 'Meta' : 'Control';
|
||||
|
||||
/**
|
||||
|
|
@ -215,7 +214,7 @@ const selectText = async (locator: Locator, text: string): Promise<void> => {
|
|||
const getTooltipText = async (page: Page, triggerElement: Locator): Promise<string> => {
|
||||
await triggerElement.hover();
|
||||
|
||||
const tooltip = page.locator(TOOLTIP_SELECTOR);
|
||||
const tooltip = page.locator(TOOLTIP_INTERFACE_SELECTOR);
|
||||
|
||||
await expect(tooltip).toBeVisible();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@ import { pathToFileURL } from 'node:url';
|
|||
import type EditorJS from '@/types';
|
||||
import type { OutputData } from '@/types';
|
||||
import { ensureEditorBundleBuilt } from '../helpers/ensure-build';
|
||||
import { EDITOR_SELECTOR } from '../constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
const TEST_PAGE_URL = pathToFileURL(
|
||||
path.resolve(__dirname, '../../../cypress/fixtures/test.html')
|
||||
).href;
|
||||
|
||||
const HOLDER_ID = 'editorjs';
|
||||
const PARAGRAPH_SELECTOR = `${EDITOR_SELECTOR} [data-block-tool="paragraph"]`;
|
||||
const INLINE_TOOLBAR_SELECTOR = `${EDITOR_SELECTOR} [data-cy=inline-toolbar]`;
|
||||
const PARAGRAPH_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} [data-block-tool="paragraph"]`;
|
||||
const INLINE_TOOLBAR_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} [data-cy=inline-toolbar]`;
|
||||
|
||||
/**
|
||||
* Reset the editor holder and destroy any existing instance
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { pathToFileURL } from 'node:url';
|
|||
import type EditorJS from '@/types';
|
||||
import type { OutputData } from '@/types';
|
||||
import { ensureEditorBundleBuilt } from '../helpers/ensure-build';
|
||||
import { INLINE_TOOLBAR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
const TEST_PAGE_URL = pathToFileURL(
|
||||
path.resolve(__dirname, '../../../cypress/fixtures/test.html')
|
||||
|
|
@ -12,7 +13,7 @@ const TEST_PAGE_URL = pathToFileURL(
|
|||
|
||||
const HOLDER_ID = 'editorjs';
|
||||
const PARAGRAPH_SELECTOR = '[data-block-tool="paragraph"]';
|
||||
const INLINE_TOOLBAR_SELECTOR = '[data-interface=inline-toolbar]';
|
||||
const INLINE_TOOLBAR_SELECTOR = INLINE_TOOLBAR_INTERFACE_SELECTOR;
|
||||
const LINK_BUTTON_SELECTOR = `${INLINE_TOOLBAR_SELECTOR} [data-item-name="link"] button`;
|
||||
const LINK_INPUT_SELECTOR = `input[data-link-tool-input-opened]`;
|
||||
const NOTIFIER_SELECTOR = '.cdx-notifies';
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ import { pathToFileURL } from 'node:url';
|
|||
import type EditorJS from '../../../../../types';
|
||||
import type { OutputData } from '../../../../../types';
|
||||
import { ensureEditorBundleBuilt } from '../../helpers/ensure-build';
|
||||
import { EDITOR_SELECTOR } from '../../constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../../src/components/constants';
|
||||
|
||||
const TEST_PAGE_URL = pathToFileURL(
|
||||
path.resolve(__dirname, '../../../../cypress/fixtures/test.html')
|
||||
).href;
|
||||
const BLOCK_SELECTOR = `${EDITOR_SELECTOR} div.ce-block`;
|
||||
const PARAGRAPH_SELECTOR = `${EDITOR_SELECTOR} [data-block-tool="paragraph"]`;
|
||||
const TOOLBAR_SELECTOR = `${EDITOR_SELECTOR} .ce-toolbar`;
|
||||
const BLOCK_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} div.ce-block`;
|
||||
const PARAGRAPH_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} [data-block-tool="paragraph"]`;
|
||||
const TOOLBAR_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} .ce-toolbar`;
|
||||
const HOLDER_ID = 'editorjs';
|
||||
|
||||
/**
|
||||
|
|
@ -520,7 +520,7 @@ test.describe('Backspace keydown', () => {
|
|||
test('should navigate to previous input when caret is not at first input', async ({ page }) => {
|
||||
await createMultiInputToolEditor(page);
|
||||
|
||||
const inputs = page.locator(`${EDITOR_SELECTOR} [data-cy=quote-tool] div[contenteditable]`);
|
||||
const inputs = page.locator(`${EDITOR_INTERFACE_SELECTOR} [data-cy=quote-tool] div[contenteditable]`);
|
||||
const lastInput = inputs.last();
|
||||
|
||||
await lastInput.click();
|
||||
|
|
@ -641,7 +641,7 @@ test.describe('Backspace keydown', () => {
|
|||
expect(blocks[0].id).toBe('block1');
|
||||
expect((blocks[0].data as { text: string }).text).toBe('First block headingSecond block paragraph');
|
||||
|
||||
await expectCaretOffset(page.locator(`${EDITOR_SELECTOR} [data-cy=block-wrapper]`).first(), 'First block heading'.length, { normalize: true });
|
||||
await expectCaretOffset(page.locator(`${EDITOR_INTERFACE_SELECTOR} [data-cy=block-wrapper]`).first(), 'First block heading'.length, { normalize: true });
|
||||
await expectToolbarClosed(page);
|
||||
});
|
||||
|
||||
|
|
@ -659,7 +659,7 @@ test.describe('Backspace keydown', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
const targetBlock = page.locator(`${EDITOR_SELECTOR} [data-cy="block-wrapper"][data-id="block2"]`);
|
||||
const targetBlock = page.locator(`${EDITOR_INTERFACE_SELECTOR} [data-cy="block-wrapper"][data-id="block2"]`);
|
||||
|
||||
await targetBlock.click();
|
||||
await targetBlock.press('Home');
|
||||
|
|
@ -671,7 +671,7 @@ test.describe('Backspace keydown', () => {
|
|||
expect(blocks[0].id).toBe('block1');
|
||||
expect((blocks[0].data as { text: string }).text).toBe('First block paragraphSecond block heading');
|
||||
|
||||
await expectCaretOffset(page.locator(`${EDITOR_SELECTOR} [data-cy=block-wrapper]`).first(), 'First block paragraph'.length, { normalize: true });
|
||||
await expectCaretOffset(page.locator(`${EDITOR_INTERFACE_SELECTOR} [data-cy=block-wrapper]`).first(), 'First block paragraph'.length, { normalize: true });
|
||||
await expectToolbarClosed(page);
|
||||
});
|
||||
|
||||
|
|
@ -687,7 +687,7 @@ test.describe('Backspace keydown', () => {
|
|||
const { blocks } = await saveEditor(page);
|
||||
|
||||
expect(blocks).toHaveLength(2);
|
||||
await expectCaretAtEnd(page.locator(`${EDITOR_SELECTOR} [data-cy=unmergeable-tool]`));
|
||||
await expectCaretAtEnd(page.locator(`${EDITOR_INTERFACE_SELECTOR} [data-cy=unmergeable-tool]`));
|
||||
await expectToolbarClosed(page);
|
||||
});
|
||||
|
||||
|
|
@ -703,7 +703,7 @@ test.describe('Backspace keydown', () => {
|
|||
const { blocks } = await saveEditor(page);
|
||||
|
||||
expect(blocks).toHaveLength(2);
|
||||
await expectCaretAtEnd(page.locator(`${EDITOR_SELECTOR} [data-cy=unmergeable-tool]`));
|
||||
await expectCaretAtEnd(page.locator(`${EDITOR_INTERFACE_SELECTOR} [data-cy=unmergeable-tool]`));
|
||||
await expectToolbarClosed(page);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import { pathToFileURL } from 'node:url';
|
|||
import type EditorJS from '../../../../../types';
|
||||
import type { OutputData } from '../../../../../types';
|
||||
import { ensureEditorBundleBuilt } from '../../helpers/ensure-build';
|
||||
import { EDITOR_SELECTOR } from '../../constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../../../src/components/constants';
|
||||
|
||||
const TEST_PAGE_URL = pathToFileURL(
|
||||
path.resolve(__dirname, '../../../../cypress/fixtures/test.html')
|
||||
).href;
|
||||
const HOLDER_ID = 'editorjs';
|
||||
const PARAGRAPH_SELECTOR = `${EDITOR_SELECTOR} [data-block-tool="paragraph"]`;
|
||||
const PARAGRAPH_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} [data-block-tool="paragraph"]`;
|
||||
const TOOL_WITH_TWO_INPUTS_SELECTOR = '[data-cy=tool-with-two-inputs] div[contenteditable=true]';
|
||||
const CONTENTLESS_TOOL_SELECTOR = '[data-cy=contentless-tool]';
|
||||
const REGULAR_INPUT_SELECTOR = '[data-cy=regular-input]';
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ import path from 'node:path';
|
|||
import { pathToFileURL } from 'node:url';
|
||||
import type { OutputData } from '@/types';
|
||||
import { ensureEditorBundleBuilt } from './helpers/ensure-build';
|
||||
import { EDITOR_SELECTOR } from './constants';
|
||||
import { EDITOR_INTERFACE_SELECTOR } from '../../../src/components/constants';
|
||||
|
||||
const TEST_PAGE_URL = pathToFileURL(
|
||||
path.resolve(__dirname, '../../cypress/fixtures/test.html')
|
||||
).href;
|
||||
|
||||
const HOLDER_ID = 'editorjs';
|
||||
const BLOCK_SELECTOR = `${EDITOR_SELECTOR} div.ce-block`;
|
||||
const BLOCK_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} div.ce-block`;
|
||||
|
||||
/**
|
||||
* Reset the editor holder and destroy any existing instance
|
||||
|
|
@ -237,7 +237,7 @@ test.describe('Sanitizing', () => {
|
|||
await selectAllText(block);
|
||||
|
||||
// Click bold button
|
||||
const boldButton = page.locator(`${EDITOR_SELECTOR} [data-item-name="bold"]`);
|
||||
const boldButton = page.locator(`${EDITOR_INTERFACE_SELECTOR} [data-item-name="bold"]`);
|
||||
|
||||
await boldButton.click();
|
||||
|
||||
|
|
@ -288,7 +288,7 @@ test.describe('Sanitizing', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
const lastParagraph = page.locator(`${EDITOR_SELECTOR} .ce-paragraph`).last();
|
||||
const lastParagraph = page.locator(`${EDITOR_INTERFACE_SELECTOR} .ce-paragraph`).last();
|
||||
|
||||
await lastParagraph.click();
|
||||
await page.keyboard.press('Home');
|
||||
|
|
@ -324,7 +324,7 @@ test.describe('Sanitizing', () => {
|
|||
|
||||
await selectAllText(block);
|
||||
|
||||
const italicButton = page.locator(`${EDITOR_SELECTOR} [data-item-name="italic"]`);
|
||||
const italicButton = page.locator(`${EDITOR_INTERFACE_SELECTOR} [data-item-name="italic"]`);
|
||||
|
||||
await italicButton.click();
|
||||
await block.click();
|
||||
|
|
@ -359,7 +359,7 @@ test.describe('Sanitizing', () => {
|
|||
|
||||
await selectAllText(block);
|
||||
|
||||
const linkButton = page.locator(`${EDITOR_SELECTOR} [data-item-name="link"]`);
|
||||
const linkButton = page.locator(`${EDITOR_INTERFACE_SELECTOR} [data-item-name="link"]`);
|
||||
|
||||
await linkButton.click();
|
||||
|
||||
|
|
@ -721,7 +721,7 @@ test.describe('Sanitizing', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
const lastParagraph = page.locator(`${EDITOR_SELECTOR} .ce-paragraph`).last();
|
||||
const lastParagraph = page.locator(`${EDITOR_INTERFACE_SELECTOR} .ce-paragraph`).last();
|
||||
|
||||
await lastParagraph.click();
|
||||
await page.keyboard.press('Home');
|
||||
|
|
@ -751,7 +751,7 @@ test.describe('Sanitizing', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
const lastParagraph = page.locator(`${EDITOR_SELECTOR} .ce-paragraph`).last();
|
||||
const lastParagraph = page.locator(`${EDITOR_INTERFACE_SELECTOR} .ce-paragraph`).last();
|
||||
|
||||
await lastParagraph.click();
|
||||
await page.keyboard.press('Home');
|
||||
|
|
|
|||
|
|
@ -4,18 +4,17 @@ import path from 'node:path';
|
|||
import { pathToFileURL } from 'node:url';
|
||||
import type { OutputData } from '@/types';
|
||||
import { PopoverItemType } from '@/types/utils/popover/popover-item-type';
|
||||
import { selectionChangeDebounceTimeout } from '../../../../src/components/constants';
|
||||
import { selectionChangeDebounceTimeout, EDITOR_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
import { ensureEditorBundleBuilt } from '../helpers/ensure-build';
|
||||
import { EDITOR_SELECTOR } from '../constants';
|
||||
|
||||
const TEST_PAGE_URL = pathToFileURL(
|
||||
path.resolve(__dirname, '../../../cypress/fixtures/test.html')
|
||||
).href;
|
||||
|
||||
const HOLDER_ID = 'editorjs';
|
||||
const BLOCK_SELECTOR = `${EDITOR_SELECTOR} .cdx-block`;
|
||||
const BLOCK_TUNES_SELECTOR = `${EDITOR_SELECTOR} [data-cy=block-tunes]`;
|
||||
const SETTINGS_BUTTON_SELECTOR = `${EDITOR_SELECTOR} .ce-toolbar__settings-btn`;
|
||||
const BLOCK_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} .cdx-block`;
|
||||
const BLOCK_TUNES_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} [data-cy=block-tunes]`;
|
||||
const SETTINGS_BUTTON_SELECTOR = `${EDITOR_INTERFACE_SELECTOR} .ce-toolbar__settings-btn`;
|
||||
const SEARCH_INPUT_SELECTOR = `${BLOCK_TUNES_SELECTOR} .cdx-search-field__input`;
|
||||
const POPOVER_ITEM_SELECTOR = `${BLOCK_TUNES_SELECTOR} .ce-popover-item`;
|
||||
const NOTHING_FOUND_SELECTOR = `${BLOCK_TUNES_SELECTOR} .ce-popover__nothing-found-message`;
|
||||
|
|
|
|||
975
test/playwright/tests/utils/tooltip.spec.ts
Normal file
975
test/playwright/tests/utils/tooltip.spec.ts
Normal file
|
|
@ -0,0 +1,975 @@
|
|||
import { expect, test } from '@playwright/test';
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
import path from 'node:path';
|
||||
import { pathToFileURL } from 'node:url';
|
||||
import { ensureEditorBundleBuilt } from '../helpers/ensure-build';
|
||||
import { TOOLTIP_INTERFACE_SELECTOR } from '../../../../src/components/constants';
|
||||
|
||||
const TEST_PAGE_URL = pathToFileURL(
|
||||
path.resolve(__dirname, '../../../cypress/fixtures/test.html')
|
||||
).href;
|
||||
|
||||
const HOLDER_ID = 'editorjs';
|
||||
|
||||
/**
|
||||
* Reset the editor holder and destroy any existing instance
|
||||
*
|
||||
* @param page - The Playwright page object
|
||||
*/
|
||||
const resetEditor = async (page: Page): Promise<void> => {
|
||||
await page.evaluate(async ({ holderId }) => {
|
||||
if (window.editorInstance) {
|
||||
await window.editorInstance.destroy?.();
|
||||
window.editorInstance = undefined;
|
||||
}
|
||||
|
||||
document.getElementById(holderId)?.remove();
|
||||
|
||||
const container = document.createElement('div');
|
||||
|
||||
container.id = holderId;
|
||||
container.dataset.cy = holderId;
|
||||
container.style.border = '1px dotted #388AE5';
|
||||
|
||||
document.body.appendChild(container);
|
||||
}, { holderId: HOLDER_ID });
|
||||
};
|
||||
|
||||
/**
|
||||
* Create editor instance
|
||||
*
|
||||
* @param page - The Playwright page object
|
||||
*/
|
||||
const createEditor = async (page: Page): Promise<void> => {
|
||||
await page.waitForFunction(() => typeof window.EditorJS === 'function');
|
||||
|
||||
await page.evaluate(async ({ holderId }) => {
|
||||
const editor = new window.EditorJS({
|
||||
holder: holderId,
|
||||
});
|
||||
|
||||
window.editorInstance = editor;
|
||||
await editor.isReady;
|
||||
}, { holderId: HOLDER_ID });
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait for tooltip to appear and verify it's visible
|
||||
*
|
||||
* @param page - The Playwright page object
|
||||
* @returns The tooltip locator
|
||||
*/
|
||||
const waitForTooltip = async (page: Page): Promise<Locator> => {
|
||||
const tooltip = page.locator(TOOLTIP_INTERFACE_SELECTOR);
|
||||
|
||||
await expect(tooltip).toBeVisible();
|
||||
|
||||
return tooltip;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait for tooltip to disappear
|
||||
*
|
||||
* @param page - The Playwright page object
|
||||
*/
|
||||
const waitForTooltipToHide = async (page: Page): Promise<void> => {
|
||||
const tooltip = page.locator(TOOLTIP_INTERFACE_SELECTOR);
|
||||
|
||||
await expect(tooltip).toBeHidden();
|
||||
};
|
||||
|
||||
test.beforeAll(() => {
|
||||
ensureEditorBundleBuilt();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(TEST_PAGE_URL);
|
||||
await resetEditor(page);
|
||||
await createEditor(page);
|
||||
});
|
||||
|
||||
test.describe('Tooltip API', () => {
|
||||
test.describe('show()', () => {
|
||||
test('should show tooltip with text content', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('button');
|
||||
|
||||
element.textContent = 'Test Button';
|
||||
element.id = 'test-button';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Test tooltip text');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toContainText('Test tooltip text');
|
||||
});
|
||||
|
||||
test('should show tooltip with HTML content', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('div');
|
||||
|
||||
element.textContent = 'Hover me';
|
||||
element.id = 'test-element';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
const htmlContent = document.createElement('div');
|
||||
|
||||
htmlContent.innerHTML = '<strong>Bold</strong> tooltip';
|
||||
editor.tooltip.show(element, htmlContent);
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip.locator('strong')).toContainText('Bold');
|
||||
await expect(tooltip).toContainText('tooltip');
|
||||
});
|
||||
|
||||
test('should show tooltip with options', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('span');
|
||||
|
||||
element.textContent = 'Test';
|
||||
element.id = 'test-span';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Tooltip with options', {
|
||||
placement: 'top',
|
||||
hidingDelay: 100,
|
||||
});
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toBeVisible();
|
||||
await expect(tooltip).toContainText('Tooltip with options');
|
||||
});
|
||||
|
||||
test('should replace existing tooltip when showing new one', async ({ page }) => {
|
||||
const testElements = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element1 = document.createElement('button');
|
||||
|
||||
element1.textContent = 'Button 1';
|
||||
element1.id = 'button-1';
|
||||
const element2 = document.createElement('button');
|
||||
|
||||
element2.textContent = 'Button 2';
|
||||
element2.id = 'button-2';
|
||||
container?.appendChild(element1);
|
||||
container?.appendChild(element2);
|
||||
|
||||
return {
|
||||
id1: element1.id,
|
||||
id2: element2.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// Show first tooltip
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'First tooltip');
|
||||
}
|
||||
}, { elementId: testElements.id1 });
|
||||
|
||||
let tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toContainText('First tooltip');
|
||||
|
||||
// Show second tooltip - should replace the first
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Second tooltip');
|
||||
}
|
||||
}, { elementId: testElements.id2 });
|
||||
|
||||
tooltip = await waitForTooltip(page);
|
||||
await expect(tooltip).toContainText('Second tooltip');
|
||||
await expect(tooltip).not.toContainText('First tooltip');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('hide()', () => {
|
||||
test('should hide visible tooltip', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('button');
|
||||
|
||||
element.textContent = 'Test Button';
|
||||
element.id = 'test-button';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// Show tooltip
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Test tooltip');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toContainText('Test tooltip');
|
||||
|
||||
// Hide tooltip
|
||||
await page.evaluate(() => {
|
||||
const editor = window.editorInstance;
|
||||
|
||||
if (editor?.tooltip) {
|
||||
editor.tooltip.hide();
|
||||
}
|
||||
});
|
||||
|
||||
await waitForTooltipToHide(page);
|
||||
});
|
||||
|
||||
test('should hide tooltip when hide() is called', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('div');
|
||||
|
||||
element.textContent = 'Test';
|
||||
element.id = 'test-element';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// Show tooltip with hiding delay
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Tooltip with delay', {
|
||||
hidingDelay: 1000,
|
||||
});
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const tooltipBeforeHide = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltipBeforeHide).toBeVisible();
|
||||
|
||||
// Hide tooltip
|
||||
await page.evaluate(() => {
|
||||
const editor = window.editorInstance;
|
||||
|
||||
if (editor?.tooltip) {
|
||||
editor.tooltip.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Should hide
|
||||
await waitForTooltipToHide(page);
|
||||
});
|
||||
|
||||
test('should handle hide() when no tooltip is visible', async ({ page }) => {
|
||||
// Calling hide() when no tooltip is visible should not throw
|
||||
await page.evaluate(() => {
|
||||
const editor = window.editorInstance;
|
||||
|
||||
if (editor?.tooltip) {
|
||||
editor.tooltip.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Verify no tooltip appears
|
||||
const tooltip = page.locator(TOOLTIP_INTERFACE_SELECTOR);
|
||||
|
||||
await expect(tooltip).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('onHover()', () => {
|
||||
test('should show tooltip on mouseenter', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('button');
|
||||
|
||||
element.textContent = 'Hover me';
|
||||
element.id = 'hover-button';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.onHover(element, 'Hover tooltip');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const button = page.locator(`#${testElement.id}`);
|
||||
|
||||
await button.hover();
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toContainText('Hover tooltip');
|
||||
});
|
||||
|
||||
test('should hide tooltip on mouseleave', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('div');
|
||||
|
||||
element.textContent = 'Hover area';
|
||||
element.id = 'hover-area';
|
||||
element.style.padding = '20px';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.onHover(element, 'Hover tooltip');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const hoverArea = page.locator(`#${testElement.id}`);
|
||||
|
||||
await hoverArea.hover();
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toBeVisible();
|
||||
|
||||
// Move mouse away
|
||||
await page.mouse.move(0, 0);
|
||||
|
||||
await waitForTooltipToHide(page);
|
||||
});
|
||||
|
||||
test('should show tooltip on hover with HTML content', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('span');
|
||||
|
||||
element.textContent = 'Rich tooltip';
|
||||
element.id = 'rich-tooltip';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
const htmlContent = document.createElement('div');
|
||||
|
||||
htmlContent.innerHTML = '<em>Italic</em> content';
|
||||
editor.tooltip.onHover(element, htmlContent);
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const element = page.locator(`#${testElement.id}`);
|
||||
|
||||
await element.hover();
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip.locator('em')).toContainText('Italic');
|
||||
await expect(tooltip).toContainText('content');
|
||||
});
|
||||
|
||||
test('should show tooltip on hover with options', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('button');
|
||||
|
||||
element.textContent = 'Configured tooltip';
|
||||
element.id = 'configured-button';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.onHover(element, 'Tooltip with config', {
|
||||
placement: 'bottom',
|
||||
delay: 200,
|
||||
});
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const button = page.locator(`#${testElement.id}`);
|
||||
|
||||
await button.hover();
|
||||
|
||||
// Wait for tooltip to appear (accounting for delay)
|
||||
const tooltip = page.locator(TOOLTIP_INTERFACE_SELECTOR);
|
||||
|
||||
await expect(tooltip).toBeVisible({ timeout: 500 });
|
||||
await expect(tooltip).toContainText('Tooltip with config');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Integration', () => {
|
||||
test('should handle multiple show/hide cycles', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('button');
|
||||
|
||||
element.textContent = 'Toggle';
|
||||
element.id = 'toggle-button';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// First cycle
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'First');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const firstTooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(firstTooltip).toContainText('First');
|
||||
|
||||
await page.evaluate(() => {
|
||||
const editor = window.editorInstance;
|
||||
|
||||
if (editor?.tooltip) {
|
||||
editor.tooltip.hide();
|
||||
}
|
||||
});
|
||||
|
||||
await waitForTooltipToHide(page);
|
||||
|
||||
// Second cycle
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Second');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toContainText('Second');
|
||||
});
|
||||
|
||||
test('should work with different element types', async ({ page }) => {
|
||||
const testElements = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const button = document.createElement('button');
|
||||
|
||||
button.textContent = 'Button';
|
||||
button.id = 'test-button';
|
||||
const div = document.createElement('div');
|
||||
|
||||
div.textContent = 'Div';
|
||||
div.id = 'test-div';
|
||||
const span = document.createElement('span');
|
||||
|
||||
span.textContent = 'Span';
|
||||
span.id = 'test-span';
|
||||
container?.appendChild(button);
|
||||
container?.appendChild(div);
|
||||
container?.appendChild(span);
|
||||
|
||||
return {
|
||||
buttonId: button.id,
|
||||
divId: div.id,
|
||||
spanId: span.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// Test with button
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Button tooltip');
|
||||
}
|
||||
}, { elementId: testElements.buttonId });
|
||||
|
||||
let tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toContainText('Button tooltip');
|
||||
|
||||
await page.evaluate(() => {
|
||||
const editor = window.editorInstance;
|
||||
|
||||
if (editor?.tooltip) {
|
||||
editor.tooltip.hide();
|
||||
}
|
||||
});
|
||||
|
||||
await waitForTooltipToHide(page);
|
||||
|
||||
// Test with div
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Div tooltip');
|
||||
}
|
||||
}, { elementId: testElements.divId });
|
||||
|
||||
tooltip = await waitForTooltip(page);
|
||||
await expect(tooltip).toContainText('Div tooltip');
|
||||
|
||||
await page.evaluate(() => {
|
||||
const editor = window.editorInstance;
|
||||
|
||||
if (editor?.tooltip) {
|
||||
editor.tooltip.hide();
|
||||
}
|
||||
});
|
||||
|
||||
await waitForTooltipToHide(page);
|
||||
|
||||
// Test with span
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Span tooltip');
|
||||
}
|
||||
}, { elementId: testElements.spanId });
|
||||
|
||||
tooltip = await waitForTooltip(page);
|
||||
await expect(tooltip).toContainText('Span tooltip');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('destroy()', () => {
|
||||
test('should destroy tooltip library and allow reinitialization', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('button');
|
||||
|
||||
element.textContent = 'Test';
|
||||
element.id = 'test-button';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// Show tooltip before destroy
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Before destroy');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
await waitForTooltip(page);
|
||||
|
||||
// Destroy editor (which calls tooltip.destroy())
|
||||
await page.evaluate(async () => {
|
||||
if (window.editorInstance) {
|
||||
await window.editorInstance.destroy();
|
||||
window.editorInstance = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
// Recreate editor
|
||||
await createEditor(page);
|
||||
|
||||
// Recreate test element if the holder was cleared during destroy
|
||||
await page.evaluate(({ holderId, elementId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
let element = document.getElementById(elementId);
|
||||
|
||||
if (!element && container) {
|
||||
element = document.createElement('button');
|
||||
element.textContent = 'Test';
|
||||
element.id = elementId;
|
||||
container.appendChild(element);
|
||||
}
|
||||
}, { holderId: HOLDER_ID,
|
||||
elementId: testElement.id });
|
||||
|
||||
// Tooltip should work after reinitialization
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'After recreate');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toContainText('After recreate');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Edge cases', () => {
|
||||
test('should handle calling onHover() multiple times on same element', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('button');
|
||||
|
||||
element.textContent = 'Hover me';
|
||||
element.id = 'hover-button';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// First onHover binding
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.onHover(element, 'First binding');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
// Second onHover binding (should replace first)
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.onHover(element, 'Second binding');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const button = page.locator(`#${testElement.id}`);
|
||||
|
||||
await button.hover();
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
// Should show the second binding
|
||||
await expect(tooltip).toContainText('Second binding');
|
||||
await expect(tooltip).not.toContainText('First binding');
|
||||
});
|
||||
|
||||
test('should handle calling show() multiple times on same element', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('div');
|
||||
|
||||
element.textContent = 'Test';
|
||||
element.id = 'test-element';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// First show
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'First show');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
let tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toContainText('First show');
|
||||
|
||||
// Second show on same element
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Second show');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
tooltip = await waitForTooltip(page);
|
||||
|
||||
// Should replace with second show
|
||||
await expect(tooltip).toContainText('Second show');
|
||||
await expect(tooltip).not.toContainText('First show');
|
||||
});
|
||||
|
||||
test('should handle empty string content', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('button');
|
||||
|
||||
element.textContent = 'Test';
|
||||
element.id = 'test-button';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, '');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
// Tooltip should still appear (even if empty)
|
||||
const tooltip = page.locator(TOOLTIP_INTERFACE_SELECTOR);
|
||||
|
||||
await expect(tooltip).toBeVisible();
|
||||
});
|
||||
|
||||
test('should handle very long content', async ({ page }) => {
|
||||
const longText = 'A'.repeat(500);
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('div');
|
||||
|
||||
element.textContent = 'Test';
|
||||
element.id = 'test-element';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId, text }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, text);
|
||||
}
|
||||
}, { elementId: testElement.id,
|
||||
text: longText });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toContainText(longText.substring(0, 100));
|
||||
});
|
||||
|
||||
test('should handle special characters in content', async ({ page }) => {
|
||||
const specialChars = '<>&"\'`';
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('span');
|
||||
|
||||
element.textContent = 'Test';
|
||||
element.id = 'test-element';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
await page.evaluate(({ elementId, text }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, text);
|
||||
}
|
||||
}, { elementId: testElement.id,
|
||||
text: specialChars });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toBeVisible();
|
||||
});
|
||||
|
||||
test('should handle interaction between show() and onHover()', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('button');
|
||||
|
||||
element.textContent = 'Test';
|
||||
element.id = 'test-button';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// First bind onHover
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.onHover(element, 'Hover tooltip');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
// Then show programmatically
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Programmatic tooltip');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
// Should show programmatic tooltip
|
||||
await expect(tooltip).toContainText('Programmatic tooltip');
|
||||
|
||||
// Hide it
|
||||
await page.evaluate(() => {
|
||||
const editor = window.editorInstance;
|
||||
|
||||
if (editor?.tooltip) {
|
||||
editor.tooltip.hide();
|
||||
}
|
||||
});
|
||||
|
||||
await waitForTooltipToHide(page);
|
||||
|
||||
// Hover should still work
|
||||
const button = page.locator(`#${testElement.id}`);
|
||||
|
||||
await button.hover();
|
||||
|
||||
const hoverTooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(hoverTooltip).toContainText('Hover tooltip');
|
||||
});
|
||||
|
||||
test('should handle hide() called multiple times', async ({ page }) => {
|
||||
const testElement = await page.evaluate(({ holderId }) => {
|
||||
const container = document.getElementById(holderId);
|
||||
const element = document.createElement('div');
|
||||
|
||||
element.textContent = 'Test';
|
||||
element.id = 'test-element';
|
||||
container?.appendChild(element);
|
||||
|
||||
return {
|
||||
id: element.id,
|
||||
};
|
||||
}, { holderId: HOLDER_ID });
|
||||
|
||||
// Show tooltip
|
||||
await page.evaluate(({ elementId }) => {
|
||||
const editor = window.editorInstance;
|
||||
const element = document.getElementById(elementId);
|
||||
|
||||
if (element && editor?.tooltip) {
|
||||
editor.tooltip.show(element, 'Test');
|
||||
}
|
||||
}, { elementId: testElement.id });
|
||||
|
||||
const tooltip = await waitForTooltip(page);
|
||||
|
||||
await expect(tooltip).toBeVisible();
|
||||
|
||||
// Call hide() multiple times
|
||||
await page.evaluate(() => {
|
||||
const editor = window.editorInstance;
|
||||
|
||||
if (editor?.tooltip) {
|
||||
editor.tooltip.hide();
|
||||
editor.tooltip.hide();
|
||||
editor.tooltip.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Should still be hidden (no errors)
|
||||
await waitForTooltipToHide(page);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
2
types/api/tooltip.d.ts
vendored
2
types/api/tooltip.d.ts
vendored
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Tooltip API
|
||||
*/
|
||||
import {TooltipContent, TooltipOptions} from 'codex-tooltip';
|
||||
import {TooltipContent, TooltipOptions} from '../../src/components/utils/tooltip';
|
||||
|
||||
export interface Tooltip {
|
||||
/**
|
||||
|
|
|
|||
1
types/index.d.ts
vendored
1
types/index.d.ts
vendored
|
|
@ -138,6 +138,7 @@ declare class EditorJS {
|
|||
public styles: Styles;
|
||||
public toolbar: Toolbar;
|
||||
public inlineToolbar: InlineToolbar;
|
||||
public tooltip: Tooltip;
|
||||
public readOnly: ReadOnly;
|
||||
constructor(configuration?: EditorConfig|string);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue