diff --git a/CHANGELOG.md b/CHANGELOG.md index b1305a4..11c16f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## 2.3.0 - 2026-05-28 + ### Changed - Updated to support jQuery 4. #INT-3359 diff --git a/Jenkinsfile b/Jenkinsfile index 93f77f6..cf845fe 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -12,7 +12,7 @@ mixedBeehiveFlow( ], testPrefix: 'Tiny-jQuery', platforms: [ - [ browser: 'chrome', headless: true ], + [ browser: 'chrome', provider: 'lambdatest', os: 'macOS Sonoma', buckets: 1 ], [ browser: 'firefox', provider: 'aws', buckets: 1 ], [ browser: 'safari', provider: 'lambdatest', os: 'macOS Sonoma', buckets: 1 ] ], diff --git a/package.json b/package.json index f363d9d..2c7aabc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tinymce/tinymce-jquery", - "version": "2.3.0-rc", + "version": "2.3.0", "description": "Official TinyMCE integration for jQuery", "main": "dist/tinymce-jquery.js", "files": [ diff --git a/src/test/ts/Utils.ts b/src/test/ts/Utils.ts index ef17967..ca35dc0 100644 --- a/src/test/ts/Utils.ts +++ b/src/test/ts/Utils.ts @@ -12,9 +12,11 @@ export const createEditor = async (action: (targetElm: JQuery, edit const targetElm = $(ce.dom); const editors = await targetElm.tinymce({ license_key: 'gpl', - base_url: '/project/node_modules/tinymce', + script_url: '/project/node_modules/tinymce/tinymce.js', }); - await Waiter.pTryUntil('Editor should be initialized', () => editors[0]?.initialized); + + await Waiter.pTryUntilPredicate('Editor should be initialized', () => editors[0]?.initialized === true); + try { const maybeAsync = action(targetElm, editors[0]); if (maybeAsync) { diff --git a/src/test/ts/browser/JqEmptyTest.ts b/src/test/ts/browser/JqEmptyTest.ts index d62cb93..a0fd9b5 100644 --- a/src/test/ts/browser/JqEmptyTest.ts +++ b/src/test/ts/browser/JqEmptyTest.ts @@ -36,7 +36,11 @@ describe('Check jQuery\'s `.empty()` function', () => { it('check empty works on a inline editor with content', async () => { await createHTML(`

Hello

World

`, async (root) => { const elm = $('div#editor'); - const ed = (await elm.tinymce({ inline: true }))[0]; + const ed = (await elm.tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }))[0]; try { Assertions.assertEq('Expected editor to have content', `

Hello

\n

World

`, ed.getContent()); elm.empty(); @@ -56,7 +60,10 @@ describe('Check jQuery\'s `.empty()` function', () => { // eslint-disable-next-line max-len await createHTML(`

Before

After

Extra

`, async (root) => { const edElm = $('textarea#editor'); - const ed = (await edElm.tinymce({ }))[0]; + const ed = (await edElm.tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + }))[0]; try { Assertions.assertEq('Expected editor to have content', `

Hello

\n

World

`, ed.getContent()); const container = $('div#container'); @@ -73,7 +80,11 @@ describe('Check jQuery\'s `.empty()` function', () => { // eslint-disable-next-line max-len await createHTML(`

Before

Hello

World

After

Extra

`, async (root) => { const edElm = $('div#editor'); - const ed = (await edElm.tinymce({ inline: true }))[0]; + const ed = (await edElm.tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }))[0]; try { Assertions.assertEq('Expected editor to have content', `

Hello

\n

World

`, ed.getContent()); const container = $('div#container'); @@ -113,8 +124,15 @@ describe('Check jQuery\'s `.empty()` function', () => { const normal = $('textarea.editor'); const eds: Editor[] = []; try { - eds.push(...await inline.tinymce({ inline: true })); - eds.push(...await normal.tinymce({ })); + eds.push(...await inline.tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + })); + eds.push(...await normal.tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + })); for (let i = 0; i < eds.length; i++) { Assertions.assertEq(`Expected editor ${i} to have content`, `

Content1

\n

Content2

`, eds[i].getContent()); } @@ -139,7 +157,10 @@ describe('Check jQuery\'s `.empty()` function', () => { it('check normal editors before and after are left alone', async () => { // eslint-disable-next-line max-len await createHTML(`

Container Content

`, async () => { - const eds = await $('textarea.editor').tinymce({ }); + const eds = await $('textarea.editor').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + }); try { for (let i = 0; i < eds.length; i++) { Assertions.assertEq(`Expected editor ${i} to have content`, `

Editor Content

`, eds[i].getContent()); @@ -162,7 +183,11 @@ describe('Check jQuery\'s `.empty()` function', () => { it('check inline editors before and after are left alone', async () => { // eslint-disable-next-line max-len await createHTML(`

Editor Content

Container Content

Editor Content

`, async () => { - const eds = await $('div.editor').tinymce({ inline: true }); + const eds = await $('div.editor').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }); try { for (let i = 0; i < eds.length; i++) { Assertions.assertEq(`Expected editor ${i} to have content`, `

Editor Content

`, eds[i].getContent()); diff --git a/src/test/ts/browser/JqRemoveTest.ts b/src/test/ts/browser/JqRemoveTest.ts index b24b268..94ec505 100644 --- a/src/test/ts/browser/JqRemoveTest.ts +++ b/src/test/ts/browser/JqRemoveTest.ts @@ -36,7 +36,10 @@ describe('Check jQuery\'s `.remove()` function', () => { await createHTML(`

Before

`, async (root) => { const target = $('div#target'); const elm = $('textarea#editor'); - const ed = (await elm.tinymce({ }))[0]; + const ed = (await elm.tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + }))[0]; try { Assertions.assertEq('Expected editor to contain content', `

Content

`, ed.getContent()); target.remove(); @@ -51,7 +54,11 @@ describe('Check jQuery\'s `.remove()` function', () => { await createHTML(`

Before

Content

`, async (root) => { const target = $('div#target'); const elm = $('div#editor'); - const ed = (await elm.tinymce({ inline: true }))[0]; + const ed = (await elm.tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }))[0]; try { Assertions.assertStructure('Expected root to initially contain everything', ApproxStructure.fromHtml(`

Before

Content

`), @@ -74,9 +81,18 @@ describe('Check jQuery\'s `.remove()` function', () => { const target = $('div.target'); const eds: Editor[] = []; try { - eds.push((await $('textarea#editor1').tinymce({ }))[0]); - eds.push((await $('textarea#editor2').tinymce({ }))[0]); - eds.push((await $('textarea#editor3').tinymce({ }))[0]); + eds.push((await $('textarea#editor1').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]); + eds.push((await $('textarea#editor2').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]); + eds.push((await $('textarea#editor3').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]); Assertions.assertEq('Expected editor 1 to contain content', `

Content

`, eds[0].getContent()); Assertions.assertEq('Expected editor 2 to contain content', `

Content

`, eds[1].getContent()); Assertions.assertEq('Expected editor 3 to contain content', `

Content

`, eds[2].getContent()); @@ -102,9 +118,21 @@ describe('Check jQuery\'s `.remove()` function', () => { const target = $('div.target'); const eds: Editor[] = []; try { - eds.push((await $('div#editor1').tinymce({ inline: true }))[0]); - eds.push((await $('div#editor2').tinymce({ inline: true }))[0]); - eds.push((await $('div#editor3').tinymce({ inline: true }))[0]); + eds.push((await $('div#editor1').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }))[0]); + eds.push((await $('div#editor2').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }))[0]); + eds.push((await $('div#editor3').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }))[0]); Assertions.assertStructure('Expected root to initially contain everything', ApproxStructure.fromHtml('
' + '

Content

' + @@ -135,7 +163,10 @@ describe('Check jQuery\'s `.remove()` function', () => { it('check works without selector on normal editors', async () => { await createHTML(`
`, async (root) => { const elm = $('textarea#editor'); - const ed = (await elm.tinymce({ }))[0]; + const ed = (await elm.tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]; try { Assertions.assertEq('Expected editor to contain content', `

Content

`, ed.getContent()); elm.remove(); @@ -149,7 +180,11 @@ describe('Check jQuery\'s `.remove()` function', () => { it('check works without selector on inline editors', async () => { await createHTML(`

Content

`, async (root) => { const elm = $('div#editor'); - const ed = (await elm.tinymce({ }))[0]; + const ed = (await elm.tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }))[0]; try { Assertions.assertEq('Expected editor to contain content', `

Content

`, ed.getContent()); elm.remove(); @@ -169,9 +204,18 @@ describe('Check jQuery\'s `.remove()` function', () => { const target = $('section.container textarea'); const eds: Editor[] = []; try { - eds.push((await $('textarea#editor1').tinymce({ }))[0]); - eds.push((await $('textarea#editor2').tinymce({ }))[0]); - eds.push((await $('textarea#editor3').tinymce({ }))[0]); + eds.push((await $('textarea#editor1').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]); + eds.push((await $('textarea#editor2').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]); + eds.push((await $('textarea#editor3').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]); Assertions.assertEq('Expected editor 1 to contain content', `

Content

`, eds[0].getContent()); Assertions.assertEq('Expected editor 2 to contain content', `

Content

`, eds[1].getContent()); Assertions.assertEq('Expected editor 3 to contain content', `

Content

`, eds[2].getContent()); @@ -197,9 +241,28 @@ describe('Check jQuery\'s `.remove()` function', () => { const target = $('section.container div'); const eds: Editor[] = []; try { - eds.push((await $('div#editor1').tinymce({ inline: true }))[0]); - eds.push((await $('div#editor2').tinymce({ inline: true }))[0]); - eds.push((await $('div#editor3').tinymce({ inline: true }))[0]); + eds.push((await $('div#editor1').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true }))[0]); + eds.push((await $('div#editor2').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true }))[0]); + eds.push((await $('div#editor3').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true }))[0]); + eds.push((await $('div#editor2').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }))[0]); + eds.push((await $('div#editor3').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + inline: true + }))[0]); Assertions.assertStructure('Expected root to initially contain everything', ApproxStructure.fromHtml('
' + '

Content

' + diff --git a/src/test/ts/browser/JqTextTest.ts b/src/test/ts/browser/JqTextTest.ts index 8594f87..d9c3aea 100644 --- a/src/test/ts/browser/JqTextTest.ts +++ b/src/test/ts/browser/JqTextTest.ts @@ -30,7 +30,10 @@ describe('Check jQuery\'s `.text()` function', () => { it('gets the text of TinyMCE and two divs', async () => { await createHTML(`

Before

Middle

After

`, async (root) => { const divs = $(root).find('div'); - const ed = (await $('#editor').tinymce({ }))[0]; + const ed = (await $('#editor').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + }))[0]; try { Assertions.assertEq('Expected matching text', 'BeforeMiddleAfter', divs.text()); } finally { @@ -54,7 +57,10 @@ describe('Check jQuery\'s `.text()` function', () => { it('sets the content of multiple things simultaneously', async () => { await createHTML(`
Before
`, async (root) => { const divs = root.querySelectorAll('div'); - const ed = (await $('#editor').tinymce({ }))[0]; + const ed = (await $('#editor').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + }))[0]; try { $(divs).text('Hello'); Assertions.assertEq('Expected matching html', 'Hello', divs[0].innerHTML); @@ -80,7 +86,10 @@ describe('Check jQuery\'s `.text()` function', () => { it('sets the content of multiple things simultaneously', async () => { await createHTML(`
Before
`, async (root) => { const divs = root.querySelectorAll('div'); - const ed = (await $('#editor').tinymce({ }))[0]; + const ed = (await $('#editor').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + }))[0]; try { $(divs).text(9007199254740991); Assertions.assertEq('Expected matching html', '9007199254740991', divs[0].innerHTML); @@ -106,7 +115,10 @@ describe('Check jQuery\'s `.text()` function', () => { it('sets the content of multiple things simultaneously', async () => { await createHTML(`
Before
`, async (root) => { const divs = root.querySelectorAll('div'); - const ed = (await $('#editor').tinymce({ }))[0]; + const ed = (await $('#editor').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]; try { $(divs).text(true); Assertions.assertEq('Expected matching html', 'true', divs[0].innerHTML); @@ -144,7 +156,10 @@ describe('Check jQuery\'s `.text()` function', () => { it('sets the content of multiple things simultaneously', async () => { await createHTML(`
Content
Content
`, async (root) => { const divs = root.querySelectorAll('div'); - const ed = (await $('#editor').tinymce({ }))[0]; + const ed = (await $('#editor').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]; try { $(divs).text(function (index, prevValue) { Assertions.assertEq('Expected matching this', divs[index], this); @@ -186,7 +201,10 @@ describe('Check jQuery\'s `.text()` function', () => { it('sets the content of multiple things simultaneously', async () => { await createHTML(`
Content
Content
`, async (root) => { const divs = root.querySelectorAll('div'); - const ed = (await $('#editor').tinymce({ }))[0]; + const ed = (await $('#editor').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]; try { $(divs).text(function (index, prevValue) { Assertions.assertEq('Expected matching this', divs[index], this); @@ -229,7 +247,10 @@ describe('Check jQuery\'s `.text()` function', () => { it('sets the content of multiple things simultaneously', async () => { await createHTML(`
Content
Content
`, async (root) => { const divs = root.querySelectorAll('div'); - const ed = (await $('#editor').tinymce({ }))[0]; + const ed = (await $('#editor').tinymce({ + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js' + }))[0]; try { $(divs).text(function (index, prevValue) { Assertions.assertEq('Expected matching this', divs[index], this); diff --git a/src/test/ts/browser/LoadTest.ts b/src/test/ts/browser/LoadTest.ts index 248b600..8cb849f 100644 --- a/src/test/ts/browser/LoadTest.ts +++ b/src/test/ts/browser/LoadTest.ts @@ -17,7 +17,6 @@ describe('LoadTest', () => { const ce = SugarElement.fromTag('div'); Class.add(ce, 'test-editor'); Insert.append(SugarBody.body(), ce); - await new Promise((resolve) => { $('div.test-editor').tinymce({ license_key: 'gpl', diff --git a/src/test/ts/browser/OriginalTest.ts b/src/test/ts/browser/OriginalTest.ts index 95ada48..f0a2720 100644 --- a/src/test/ts/browser/OriginalTest.ts +++ b/src/test/ts/browser/OriginalTest.ts @@ -96,7 +96,10 @@ describe('OriginalTest', () => { }); it('applyPatch is only called once', () => { - const options = {}; + const options = { + license_key: 'gpl', + script_url: '/project/node_modules/tinymce/tinymce.js', + }; $('#elm1').tinymce(options).catch((err) => { /* eslint-disable-next-line no-console */