From fc501add942230f50d286a5fcc2cf166642c319e Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Mon, 19 Aug 2024 14:11:07 +0100 Subject: [PATCH] Fixed editor not loading in Admin acceptance tests closes https://linear.app/tryghost/issue/PLG-176 The editor files were previously stubbed for testing because we didn't have a way to load the externally-hosted files. This made testing slow and difficult because the only way to test the Admin integration was via Ghost's e2e browser tests. - unstubbed the editor globals so `fetchKoenigLexical()` actually tries to import the external assets - updated `ember-cli-build` to copy the Koenig UMD file over to the assets directory in development/test builds - updated `environment.js` to set the required filename for the default asset import to successfully hit the test environment hosted files - updated lexical editor acceptance tests to demonstrate the editor loads successfully for new and existing posts --- ghost/admin/config/environment.js | 9 +++++++- ghost/admin/ember-cli-build.js | 6 +++++ .../tests/acceptance/editor/lexical-test.js | 23 +++++++++++++++---- .../acceptance/editor/post-revisions-test.js | 14 ++++++----- ghost/admin/tests/test-helper.js | 6 ----- 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/ghost/admin/config/environment.js b/ghost/admin/config/environment.js index 5deea6c31e..d77a92194f 100644 --- a/ghost/admin/config/environment.js +++ b/ghost/admin/config/environment.js @@ -66,10 +66,17 @@ module.exports = function (environment) { ENV.APP.rootElement = '#ember-testing'; ENV.APP.autoboot = false; - // Withuot manually setting this, pretender won't track requests + // Without manually setting this, pretender won't track requests ENV['ember-cli-mirage'] = { trackRequests: true }; + + // We copy the dynamically loaded editor file into the ghost assets + // directory in the dev/test env so that tests can load it. We need to + // set the config appropriately here so that the fetchKoenigLexical + // utility creates the right URL + ENV.editorFilename = 'koenig-lexical.umd.js'; + ENV.editorHash = 'test'; } return ENV; diff --git a/ghost/admin/ember-cli-build.js b/ghost/admin/ember-cli-build.js index cd31800556..684a6af97a 100644 --- a/ghost/admin/ember-cli-build.js +++ b/ghost/admin/ember-cli-build.js @@ -254,5 +254,11 @@ module.exports = function (defaults) { app.import('vendor/codemirror/lib/codemirror.js', {type: 'test'}); } + if (app.env === 'development' || app.env === 'test') { + // pull dynamic imports into the assets folder so that they can be lazy-loaded in tests + // also done in development env so http://localhost:4200/tests works + app.import('node_modules/@tryghost/koenig-lexical/dist/koenig-lexical.umd.js', {outputFile: 'ghost/assets/koenig-lexical/koenig-lexical.umd.js'}); + } + return app.toTree(); }; diff --git a/ghost/admin/tests/acceptance/editor/lexical-test.js b/ghost/admin/tests/acceptance/editor/lexical-test.js index ab8c527636..27b98bfaf8 100644 --- a/ghost/admin/tests/acceptance/editor/lexical-test.js +++ b/ghost/admin/tests/acceptance/editor/lexical-test.js @@ -1,5 +1,5 @@ import loginAsRole from '../../helpers/login-as-role'; -import {blur, click, currentURL, fillIn, find, waitUntil} from '@ember/test-helpers'; +import {blur, click, currentURL, fillIn, find, waitFor, waitUntil} from '@ember/test-helpers'; import {enableLabsFlag} from '../../helpers/labs-flag'; import {expect} from 'chai'; import {invalidateSession} from 'ember-simple-auth/test-support'; @@ -18,15 +18,21 @@ describe('Acceptance: Lexical editor', function () { it('redirects to signin when not authenticated', async function () { await invalidateSession(); + await visit('/editor/post/'); expect(currentURL(), 'currentURL').to.equal('/signin'); }); - describe('new post', function () { - // TODO: test it actually loads the editor + describe('with new post', function () { it('loads editor', async function () { await visit('/editor/post/'); expect(currentURL(), 'currentURL').to.equal('/editor/post/'); + + await waitFor('[data-secondary-instance="false"] [data-lexical-editor]'); + // find the placeholder div + const xpath = '//div[text()="Begin writing your post..."]'; + const match = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); + expect(match.singleNodeValue).to.exist; }); it('can leave editor without unsaved changes modal', async function () { @@ -72,7 +78,16 @@ describe('Acceptance: Lexical editor', function () { it('saves on content change'); }); - describe('existing post', function () { + describe('with existing post', function () { + it('loads editor', async function () { + const post = this.server.create('post', {lexical: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"This is a test","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}'}); + await visit(`/editor/post/${post.id}`); + expect(currentURL(), 'currentURL').to.equal(`/editor/post/${post.id}`); + await waitFor('[data-secondary-instance="false"] [data-lexical-editor]'); + // find the post content + expect(find('[data-secondary-instance="false"] [data-lexical-editor]')).to.contain.text('This is a test'); + }); + it('does not save post on title blur', async function () { const post = this.server.create('post', {status: 'published'}); const originalTitle = post.title; diff --git a/ghost/admin/tests/acceptance/editor/post-revisions-test.js b/ghost/admin/tests/acceptance/editor/post-revisions-test.js index b8606480d4..2c9df145eb 100644 --- a/ghost/admin/tests/acceptance/editor/post-revisions-test.js +++ b/ghost/admin/tests/acceptance/editor/post-revisions-test.js @@ -33,7 +33,8 @@ describe('Acceptance: Post revisions', function () { postStatus: 'draft', author: post.authors.models[0], createdAt: moment(post.updatedAt).subtract(1, 'hour'), - reason: 'explicit_save' + reason: 'explicit_save', + lexical: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"New body","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}' }); this.server.create('post-revision', { post, @@ -45,11 +46,10 @@ describe('Acceptance: Post revisions', function () { postStatus: 'draft', author: post.authors.models[0], createdAt: moment(post.updatedAt).subtract(1, 'day'), - reason: 'initial_revision' + reason: 'initial_revision', + lexical: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Old body","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}' }); - // this.timeout(0); - await visit(`/editor/post/${post.id}`); // open post history menu @@ -109,7 +109,8 @@ describe('Acceptance: Post revisions', function () { postStatus: 'draft', author: post.authors.models[0], createdAt: moment(post.updatedAt).subtract(1, 'hour'), - reason: 'explicit_save' + reason: 'explicit_save', + lexical: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"New body","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}' }); this.server.create('post-revision', { post, @@ -118,7 +119,8 @@ describe('Acceptance: Post revisions', function () { postStatus: 'draft', author: post.authors.models[0], createdAt: moment(post.updatedAt).subtract(1, 'day'), - reason: 'initial_revision' + reason: 'initial_revision', + lexical: '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Old body","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}' }); await visit(`/editor/post/${post.id}`); diff --git a/ghost/admin/tests/test-helper.js b/ghost/admin/tests/test-helper.js index 447f279d76..756802bcd0 100644 --- a/ghost/admin/tests/test-helper.js +++ b/ghost/admin/tests/test-helper.js @@ -8,12 +8,6 @@ import chai from 'chai'; import chaiDom from 'chai-dom'; chai.use(chaiDom); -// stub loaded external module to avoid loading of external dep -window['@tryghost/koenig-lexical'] = { - KoenigComposer: () => null, - KoenigEditor: () => null -}; - setApplication(Application.create(config.APP)); registerWaiter();