import { ApproxStructure, Assertions, Logger, RawAssertions } from '@ephox/agar';
import { UnitTest } from '@ephox/bedrock';
import { FieldSchema, Objects, ValueSchema } from '@ephox/boulder';
import { Cell, Fun, Option } from '@ephox/katamari';
import { Element } from '@ephox/sugar';
import LinkBridge from 'tinymce/themes/mobile/bridge/LinkBridge';
import TestStore from '../../module/test/TestStore';
UnitTest.test('Test: phantom.bridge.LinkBridgeTest', function () {
const store = TestStore();
const editorState = {
start: Cell(null),
content: Cell('')
};
const editor = {
selection: {
getStart: editorState.start.get,
getContent: editorState.content.get,
select: Fun.noop
},
insertContent (data) {
store.adder({ method: 'insertContent', data })();
},
execCommand (name) {
store.adder({ method: 'execCommand', data: name })();
},
dom: {
createHTML (tag, attributes, innerText) {
return { tag, attributes, innerText };
},
encode: Fun.identity
},
focus: Fun.noop
};
const checkGetNoLink = function (rawScenario) {
const schema = ValueSchema.objOfOnly([
FieldSchema.strict('label'),
FieldSchema.defaulted('nodeText', ''),
FieldSchema.defaulted('selection', ''),
FieldSchema.strict('expected')
]);
const scenario = ValueSchema.asRawOrDie(rawScenario.label, schema, rawScenario);
Logger.sync('getInfo ... ' + scenario.label, function () {
editorState.start.set(Element.fromText(scenario.nodeText).dom());
editorState.content.set(scenario.selection);
const info = LinkBridge.getInfo(editor);
RawAssertions.assertEq('Checking getInfo (no link)', {
url: '',
text: scenario.expected,
title: '',
target: ''
}, Objects.narrow(info, [ 'url', 'text', 'target', 'title' ]));
RawAssertions.assertEq('Checking link is not set', true, info.link.isNone());
});
};
const checkGetALink = function (rawScenario) {
const schema = ValueSchema.objOfOnly([
FieldSchema.strict('label'),
FieldSchema.defaulted('linkHtml', ''),
FieldSchema.defaulted('selection', ''),
FieldSchema.strict('expected')
]);
const scenario = ValueSchema.asRawOrDie(rawScenario.label, schema, rawScenario);
Logger.sync('getInfo ... ' + scenario.label + ', link: ' + scenario.linkHtml, function () {
editorState.start.set(Element.fromHtml(scenario.linkHtml).dom());
editorState.content.set(scenario.selection);
const info = LinkBridge.getInfo(editor);
RawAssertions.assertEq('Checking getInfo (link)', scenario.expected, Objects.narrow(info, [ 'url', 'text', 'target', 'title' ]));
RawAssertions.assertEq('Checking link is set', true, info.link.isSome());
});
};
const checkApply = function (rawScenario) {
const schema = ValueSchema.objOfOnly([
FieldSchema.strict('label'),
FieldSchema.strictObjOf('info', [
FieldSchema.option('url'),
FieldSchema.option('text'),
FieldSchema.option('title'),
FieldSchema.option('target'),
FieldSchema.option('link')
]),
FieldSchema.defaulted('mutations', Fun.noop),
FieldSchema.defaulted('expected', [ ])
]);
const scenario = ValueSchema.asRawOrDie(rawScenario.label, schema, rawScenario);
Logger.sync('setInfo ... ' + scenario.label, function () {
store.clear();
LinkBridge.applyInfo(editor, scenario.info);
store.assertEq('Checking store', scenario.expected);
const link = scenario.info.link.bind(Fun.identity);
link.each(scenario.mutations);
});
};
checkGetNoLink({
label: 'Basic text node with no text',
expected: ''
});
checkGetNoLink({
label: 'Basic text node with some text and no selection',
nodeText: 'some',
expected: ''
});
checkGetNoLink({
label: 'Basic text node with some text and "sel" selection',
nodeText: 'some',
selection: 'sel',
expected: 'sel'
});
checkGetALink({
label: 'Link with href',
linkHtml: 'Foo',
selection: 'sel',
expected: {
url: 'http://foo',
text: 'Foo',
title: '',
target: ''
}
});
checkGetALink({
label: 'Link with href and target',
linkHtml: 'Foo',
selection: 'sel',
expected: {
url: 'http://foo',
text: 'Foo',
title: '',
target: '_blank'
}
});
checkGetALink({
label: 'Link with href and target and title',
linkHtml: 'Foo',
selection: 'sel',
expected: {
url: 'http://foo',
text: 'Foo',
title: 'wow',
target: '_blank'
}
});
checkGetALink({
label: 'Link with href and matching text (should ignore text)',
linkHtml: 'http://foo',
selection: 'sel',
expected: {
url: 'http://foo',
text: '',
title: '',
target: ''
}
});
checkApply({
label: 'Applying to empty text',
info: {
url: 'hi'
},
mutations (elem) {
},
expected: [
{
method: 'insertContent',
data: {
tag: 'a',
attributes: {
href: 'hi'
},
innerText: 'hi'
}
}
]
});
checkApply({
label: 'Applying to empty text with [ text ]',
info: {
url: 'hi',
text: 'hello'
},
mutations (elem) {
},
expected: [
{
method: 'insertContent',
data: {
tag: 'a',
attributes: {
href: 'hi'
},
innerText: 'hello'
}
}
]
});
checkApply({
label: 'Applying to empty text with [ text, title ]',
info: {
url: 'hi',
text: 'hello',
title: 'Title'
},
mutations (elem) {
},
expected: [
{
method: 'insertContent',
data: {
tag: 'a',
attributes: {
href: 'hi',
title: 'Title'
},
innerText: 'hello'
}
}
]
});
checkApply({
label: 'Applying to empty text with [ text, title, target ]',
info: {
url: 'hi',
text: 'hello',
title: 'Title',
target: 'new'
},
mutations (elem) {
},
expected: [
{
method: 'insertContent',
data: {
tag: 'a',
attributes: {
href: 'hi',
title: 'Title',
target: 'new'
},
innerText: 'hello'
}
}
]
});
checkApply({
label: 'Applying to simple link (http://foo) with url',
info: {
url: 'hi',
text: '',
title: '',
target: '',
link: Option.some(
Element.fromHtml('http://foo')
)
},
mutations (elem) {
Assertions.assertStructure('Checking structure', ApproxStructure.build(function (s, str, arr) {
return s.element('a', {
attrs: {
href: str.is('hi')
},
html: str.is('hi')
});
}), elem);
}
});
checkApply({
label: 'Applying to complex link (http://foo), Foo with url',
info: {
url: 'hi',
text: '',
title: '',
target: '',
link: Option.some(
Element.fromHtml('Foo')
)
},
mutations (elem) {
Assertions.assertStructure('Checking structure', ApproxStructure.build(function (s, str, arr) {
return s.element('a', {
attrs: {
href: str.is('hi')
},
html: str.is('Foo')
});
}), elem);
}
});
checkApply({
label: 'Applying to complex link (http://foo), Foo with url, text, and title',
info: {
url: 'hi',
text: 'new-text',
title: 'new-title',
target: '',
link: Option.some(
Element.fromHtml('Foo')
)
},
mutations (elem) {
Assertions.assertStructure('Checking structure', ApproxStructure.build(function (s, str, arr) {
return s.element('a', {
attrs: {
href: str.is('hi'),
title: str.is('new-title')
},
html: str.is('new-text')
});
}), elem);
}
});
checkApply({
label: 'Unlinking a link by removing the URL',
info: {
url: '',
text: 'new-text',
title: 'new-title',
target: '',
link: Option.some(
Element.fromHtml('Foo')
)
},
expected: [
{
method: 'execCommand',
data: 'unlink'
}
]
});
checkApply({
label: 'Unlinking should not be called if there is no existing link',
info: {
url: '',
text: 'new-text',
title: 'new-title',
target: '',
link: Option.none()
},
expected: [ ]
});
});