-
Notifications
You must be signed in to change notification settings - Fork 9
INT-3358: Remove @tinymce/miniature from dependency #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tiny-ben-tran
wants to merge
29
commits into
main
Choose a base branch
from
feature/INT-3358
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
f1ea6e7
Replace ts-node with tsx for running the demo due to an compatibility…
tiny-ben-tran fe823e3
INT-3358: Remove tinymce/miniature as dependency
tiny-ben-tran 5020b0a
INT-3358: Remove @tinymce/miniature dependency
tiny-ben-tran ccda14f
Update test
tiny-ben-tran 623bc37
Add more tests
tiny-ben-tran 313577f
Update changelog
tiny-ben-tran 47f9413
Correct ticket number in the changelog
tiny-ben-tran 02ce3c5
Fix lining errors
tiny-ben-tran 06ce570
Remove the accidentally added file
tiny-ben-tran f87ea90
Bump minor and corrected the heading in changelog
tiny-ben-tran cb188a9
Fixed tests
tiny-ben-tran b5e2bae
Remove eslint errors
tiny-ben-tran a94d177
Fix timeout and refactor
tiny-ben-tran 631d802
Ignore pre-const lint error
tiny-ben-tran 6bb424a
Move tinymce to dev
tiny-ben-tran 001c1bb
Attempt to resolve a race condition
tiny-ben-tran c8b9043
Another go
tiny-ben-tran 011d056
Run one test
tiny-ben-tran 183f113
Repeat
tiny-ben-tran 0e528d5
Run just one test
tiny-ben-tran 3bbe818
Run disbledtest only
tiny-ben-tran 842d0f6
Try again
tiny-ben-tran ff7b1d0
Fix lint errors
tiny-ben-tran f09c73e
Another try
tiny-ben-tran 9448c31
Remove duplicated test
tiny-ben-tran f5a7108
Clear loader saved url
tiny-ben-tran 789ac6f
Fix test failing
tiny-ben-tran 977fd85
Give headless browser some time to fetch stuffs
tiny-ben-tran 4a7e3a2
Resolve comments
tiny-ben-tran File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import { Attribute, Remove, SelectorFilter, SugarElement } from '@ephox/sugar'; | ||
| import { ScriptLoader } from 'src/main/ts/utils/ScriptLoader'; | ||
| import { Arr, Strings, Optional, Fun } from '@ephox/katamari'; | ||
| // eslint-disable-next-line @tinymce/no-direct-imports | ||
| import * as Globals from '@tinymce/miniature/lib/main/ts/loader/Globals'; | ||
| import Editor from 'src/main/ts/component/Editor'; | ||
|
|
||
| export const deleteTinymce = () => { | ||
| ScriptLoader.reinitialize(); | ||
| Globals.deleteTinymceGlobals(); | ||
|
|
||
| const hasTinyUri = (attrName: string) => (elm: SugarElement<Element>) => | ||
| Attribute.getOpt(elm, attrName).exists((src) => Strings.contains(src, 'tinymce')); | ||
|
|
||
| const elements = Arr.flatten([ | ||
| Arr.filter(SelectorFilter.all('script'), hasTinyUri('src')), | ||
| Arr.filter(SelectorFilter.all('link'), hasTinyUri('href')), | ||
| ]); | ||
|
|
||
| Arr.each(elements, Remove.remove); | ||
| }; | ||
|
|
||
| export const removeTinymceElements = () => { | ||
| Arr.each(SelectorFilter.all('tinymce-editor'), Remove.remove); | ||
| }; | ||
|
|
||
| export const registerCustomElementIfNot = () => { | ||
| Optional.from(window.customElements?.get('tinymce-editor')).fold(Editor, Fun.noop); | ||
| }; | ||
|
|
||
| export const createTinymceElement = (attrs: Record<string, string>, content?: string) => { | ||
| const ce = SugarElement.fromTag('tinymce-editor'); | ||
| Attribute.setAll(ce, attrs); | ||
| if (content) { | ||
| ce.dom.innerHTML = content; | ||
| } | ||
| document.body.appendChild(ce.dom); | ||
| return ce; | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| import { Assertions } from '@ephox/agar'; | ||
| import { before, describe, it, context, after, afterEach } from '@ephox/bedrock-client'; | ||
| import { Global } from '@ephox/katamari'; | ||
| import type { Editor, TinyMCE, Editor as TinyMCEEditor } from 'tinymce'; | ||
| import { VersionLoader, TinyVer } from '@tinymce/miniature'; | ||
| import { createTinymceElement, deleteTinymce, registerCustomElementIfNot, removeTinymceElements } from '../alien/Utils'; | ||
| import { Attribute, SugarElement } from '@ephox/sugar'; | ||
|
|
||
| type EditorElement = HTMLElement & { disabled?: boolean }; | ||
| declare const tinymce: TinyMCE; | ||
|
|
||
| describe('DisableTest', () => { | ||
| let uid = 0; | ||
| const nextId = () => `_disabled_test_fn_${uid++}`; | ||
|
|
||
| before(() => { | ||
| registerCustomElementIfNot(); | ||
| Global.tinymceTestConfig = { license_key: 'gpl' }; | ||
| }); | ||
|
|
||
| after(() => { | ||
| delete Global.tinymceTestConfig; | ||
| }); | ||
|
|
||
| const pCreateEditor = | ||
| (attrs: Record<string, string> = {}): Promise<{ element: SugarElement<EditorElement>; editor: TinyMCEEditor }> => new Promise((resolve) => { | ||
| const setupFnName = nextId(); | ||
| // eslint-disable-next-line prefer-const | ||
| let tinymceEl: SugarElement<EditorElement>; | ||
|
|
||
| Global[setupFnName] = (editor: Editor) => { | ||
| editor.on('SkinLoaded', () => { | ||
| setTimeout(() => resolve({ element: tinymceEl, editor }), 500); | ||
| }); | ||
| }; | ||
|
|
||
| tinymceEl = createTinymceElement({ | ||
| setup: setupFnName, | ||
| config: 'tinymceTestConfig', | ||
| ...attrs | ||
| }); | ||
| }); | ||
|
|
||
| context('When using with Tinymce < 7.6', () => { | ||
| before(async () => { | ||
| await VersionLoader.pLoadVersion('7.5.0'); | ||
| Assertions.assertEq('Tinymce 7.5.0 should be loaded', | ||
| '7.5.0', | ||
| TinyVer.getVersion(tinymce).major + '.' + TinyVer.getVersion(tinymce).minor + '.' + TinyVer.getVersion(tinymce).patch); | ||
| }); | ||
|
|
||
| after(() => { | ||
| deleteTinymce(); | ||
| }); | ||
|
|
||
| it('Editor should be not be disabled when disabled attribute is present', async () => { | ||
| const { editor } = await pCreateEditor(); | ||
| Assertions.assertEq('Editor should be in design mode', true, editor.mode.get() === 'design'); | ||
| removeTinymceElements(); | ||
| }); | ||
| }); | ||
|
|
||
| context('When using with Tinymce >= 7.6', () => { | ||
| before(async () => { | ||
| await VersionLoader.pLoadVersion('8'); | ||
| Assertions.assertEq('Tinymce 8 should be loaded', '8', TinyVer.getVersion(tinymce).major + ''); | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| removeTinymceElements(); | ||
| }); | ||
|
|
||
| after(() => { | ||
| deleteTinymce(); | ||
| }); | ||
|
|
||
| const pWaitForDisabledStateChange = (editor: any): Promise<void> => | ||
| new Promise((resolve) => editor.once('DisabledStateChange', resolve)); | ||
|
|
||
| const assertDisabledState = (el: SugarElement<EditorElement>, editor: TinyMCEEditor, expected: boolean) => { | ||
| const hasDisabledAtt = Attribute.has(el, 'disabled'); | ||
| Assertions.assertEq('Editor should be disabled', expected, editor.options.get('disabled')); | ||
| Assertions.assertEq(`disabled attribute should be ${expected ? 'present' : 'absent'}`, expected, hasDisabledAtt); | ||
| }; | ||
|
|
||
| it('Editor should be disabled when disabled attribute is present', async () => { | ||
| const { element, editor } = await pCreateEditor({ disabled: '' }); | ||
| assertDisabledState(element, editor, true); | ||
| }); | ||
|
|
||
| it('Editor is not disabled when disabled attribute is absent', async () => { | ||
| const { element, editor } = await pCreateEditor(); | ||
| assertDisabledState(element, editor, false); | ||
| }); | ||
|
|
||
| it('Setting disabled attribute after init disables the editor', async () => { | ||
| const { element, editor } = await pCreateEditor(); | ||
| assertDisabledState(element, editor, false); | ||
| Attribute.set(element, 'disabled', ''); | ||
| await pWaitForDisabledStateChange(editor); | ||
| assertDisabledState(element, editor, true); | ||
| }); | ||
|
|
||
| it('Removing disabled attribute after init enables the editor', async () => { | ||
| const { element, editor } = await pCreateEditor({ disabled: '' }); | ||
| assertDisabledState(element, editor, true); | ||
| Attribute.remove(element, 'disabled'); | ||
| await pWaitForDisabledStateChange(editor); | ||
| assertDisabledState(element, editor, false); | ||
| }); | ||
|
|
||
| it('Updating disabled property directly syncs editor option and attribute', async () => { | ||
| const { element, editor } = await pCreateEditor(); | ||
| Assertions.assertEq('disabled property should be false initially', false, element.dom.disabled); | ||
| element.dom.disabled = true; | ||
| await pWaitForDisabledStateChange(editor); | ||
| assertDisabledState(element, editor, true); | ||
| element.dom.disabled = false; | ||
| await pWaitForDisabledStateChange(editor); | ||
| assertDisabledState(element, editor, false); | ||
| }); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,50 +1,48 @@ | ||
| import { Pipeline, Step, Waiter, Assertions } from '@ephox/agar'; | ||
| import { SugarElement, Attribute, SugarBody, Insert, Remove, SelectorFilter, TextContent } from '@ephox/sugar'; | ||
| import { UnitTest } from '@ephox/bedrock-client'; | ||
| import Editor from '../../../main/ts/component/Editor'; | ||
| import { Arr, Global } from '@ephox/katamari'; | ||
| import { Assertions } from '@ephox/agar'; | ||
| import { before, describe, after, it } from '@ephox/bedrock-client'; | ||
| import { Global } from '@ephox/katamari'; | ||
| import { createTinymceElement, deleteTinymce, registerCustomElementIfNot, removeTinymceElements } from '../alien/Utils'; | ||
| import { Editor } from 'tinymce'; | ||
| import { VersionLoader } from '@tinymce/miniature'; | ||
|
|
||
| const makeTinymceElement = (attrs: Record<string, string>, content: string) => { | ||
| const ce = SugarElement.fromTag('tinymce-editor'); | ||
| Attribute.set(ce, 'channel', '8'); | ||
| Attribute.setAll(ce, attrs); | ||
| TextContent.set(ce, content); | ||
| Insert.append(SugarBody.body(), ce); | ||
| }; | ||
| describe('LoadTest', () => { | ||
| before(async () => { | ||
| await VersionLoader.pLoadVersion('8'); | ||
| registerCustomElementIfNot(); | ||
| Global.tinymceTestConfig = { license_key: 'gpl' }; | ||
| }); | ||
|
|
||
| const removeTinymceElement = () => { | ||
| Arr.map(SelectorFilter.all('tinymce-editor'), Remove.remove); | ||
| }; | ||
| after(() => { | ||
| delete Global.tinymceTestConfig; | ||
| deleteTinymce(); | ||
| }); | ||
|
|
||
| UnitTest.asynctest('LoadTest', (success, failure) => { | ||
| Editor(); | ||
| let seenSetup = false; | ||
| let seenInit = false; | ||
| let editorInstance: any; | ||
| Pipeline.async('', [ | ||
| Step.sync(() => { | ||
| Global.customElementTinymceSetup = (editor: any) => { | ||
| it('Should load the editor and execute setup and init callbacks', async () => { | ||
| let seenSetup = false; | ||
| let seenInit = false; | ||
|
|
||
| const { editor } = await new Promise<{ editor: Editor }>((resolve) => { | ||
| Global.customElementTinymceSetup = (ed: Editor) => { | ||
| seenSetup = true; | ||
| editorInstance = editor; | ||
| ed.on('SkinLoaded', () => { | ||
| setTimeout(() => resolve({ editor: ed }), 500); | ||
| }); | ||
| }; | ||
| Global.customElementTinymceInit = (_evt: unknown) => { | ||
| seenInit = true; | ||
| }; | ||
| }), | ||
| Step.sync(() => makeTinymceElement({ | ||
| 'setup': 'customElementTinymceSetup', | ||
| 'on-init': 'customElementTinymceInit', | ||
| 'id': 'example_id' | ||
| }, '<p>Hello world</p>')), | ||
| Waiter.sTryUntilPredicate('Waiting for editor setup', () => seenSetup), | ||
| Waiter.sTryUntilPredicate('Waiting for editor init', () => seenInit), | ||
| Step.sync(() => { | ||
| Assertions.assertHtmlStructure('', '<p>Hello world</p>', editorInstance.getContent() as string); | ||
| Assertions.assertEq('An editor instance is registered', true, Global.tinymce.get('example_id') !== null); | ||
| }), | ||
| Step.sync(() => removeTinymceElement()), | ||
| Step.sync(() => { | ||
| Assertions.assertEq('The editor instance is removed', true, Global.tinymce.get('example_id') === null); | ||
| }) | ||
| ], success, failure); | ||
| createTinymceElement({ | ||
| 'setup': 'customElementTinymceSetup', | ||
| 'on-init': 'customElementTinymceInit', | ||
| 'config': 'tinymceTestConfig', | ||
| 'id': 'example_id' | ||
| }, '<p>Hello world</p>'); | ||
| }); | ||
|
|
||
| Assertions.assertEq('Editor setup callback should be called', true, seenSetup); | ||
| Assertions.assertEq('Editor init callback should be called', true, seenInit); | ||
| Assertions.assertEq('An editor instance is registered', true, Global.tinymce.get('example_id') !== null); | ||
| Assertions.assertHtmlStructure('The editor has the correct content', '<p>Hello world</p>', editor.getContent() as string); | ||
| removeTinymceElements(); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh dear. This really isn't good, but I can understand how it happened. We probably need a
miniatureexport to help cases like this where the integration creates the editor instance, not miniature itself. Can you make a tech debt task for that please?