diff --git a/app/controllers/pageflow/entries_controller.rb b/app/controllers/pageflow/entries_controller.rb index a68a079279..aca03922da 100644 --- a/app/controllers/pageflow/entries_controller.rb +++ b/app/controllers/pageflow/entries_controller.rb @@ -119,7 +119,10 @@ def entry_redirect(entry) end def delegate_to_entry_type_frontend_app!(entry, override_status: nil) - EntriesControllerEnvHelper.add_entry_info_to_env(request.env, entry:, mode: :published) + EntriesControllerEnvHelper.add_entry_info_to_env(request.env, + entry:, + mode: :published, + embed: params[:embed].present?) delegate_to_rack_app!(entry.entry_type.frontend_app) do |result| status, headers, body = result diff --git a/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb b/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb index dce013eef3..a62fdbaaab 100644 --- a/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +++ b/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb @@ -21,7 +21,11 @@ def show render( locals: { entry:, - widget_scope: get_entry_mode_from_env + widget_scope: get_entry_mode_from_env, + seed_options: { + embed: get_embed_from_env, + origin_url: request.original_url + } } ) end diff --git a/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb b/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb index e7f4b1349e..362814f2a5 100644 --- a/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +++ b/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb @@ -4,9 +4,9 @@ module ReactServerSideRenderingHelper include Pageflow::RenderJsonHelper include PageflowScrolled::EntryJsonSeedHelper - def render_scrolled_entry(entry) + def render_scrolled_entry(entry, options = {}) seed_json = render_json do |json| - scrolled_entry_json_seed(json, entry) + scrolled_entry_json_seed(json, entry, options) end ReactServerSideRenderingHelper.renderer.render('Root', "{seed: #{seed_json}}", {}) diff --git a/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb b/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb index e3c1b04c40..ab1cab5b01 100644 --- a/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +++ b/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb @@ -35,7 +35,7 @@ <% end %> - <% ssr_html = local_assigns[:skip_ssr] ? '' : render_scrolled_entry(entry) %> + <% ssr_html = local_assigns[:skip_ssr] ? '' : render_scrolled_entry(entry, local_assigns[:seed_options] || {}) %> <% if !local_assigns[:skip_ssr] && (params[:frontend] == 'v2' || entry.feature_state('frontend_v2')) %> <%= generated_media_queries_tags_for(ssr_html) %> diff --git a/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder b/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder index a0d3000505..c4c369b64b 100644 --- a/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +++ b/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder @@ -48,6 +48,8 @@ json.config do ) json.cut_off entry.cutoff_mode_enabled_for?(request) + json.embed options.fetch(:embed, false) + json.origin_url options[:origin_url] if options[:origin_url] end unless options[:skip_i18n] diff --git a/entry_types/scrolled/package/spec/entryState/embedOriginUrl-spec.js b/entry_types/scrolled/package/spec/entryState/embedOriginUrl-spec.js new file mode 100644 index 0000000000..a18449faf0 --- /dev/null +++ b/entry_types/scrolled/package/spec/entryState/embedOriginUrl-spec.js @@ -0,0 +1,43 @@ +import {useEmbedOriginUrl} from 'entryState'; + +import {renderHookInEntry} from 'support'; + +describe('useEmbedOriginUrl', () => { + it('returns undefined when embed is false', () => { + const {result} = renderHookInEntry( + () => useEmbedOriginUrl(), { + seed: { + embed: false, + originUrl: 'https://example.com/my-entry' + } + } + ); + + expect(result.current).toBeUndefined(); + }); + + it('returns undefined when embed is true but originUrl not set', () => { + const {result} = renderHookInEntry( + () => useEmbedOriginUrl(), { + seed: { + embed: true + } + } + ); + + expect(result.current).toBeUndefined(); + }); + + it('returns originUrl when embed is true and originUrl is set', () => { + const {result} = renderHookInEntry( + () => useEmbedOriginUrl(), { + seed: { + embed: true, + originUrl: 'https://example.com/my-entry' + } + } + ); + + expect(result.current).toEqual('https://example.com/my-entry'); + }); +}); diff --git a/entry_types/scrolled/package/spec/frontend/EditableLink-spec.js b/entry_types/scrolled/package/spec/frontend/EditableLink-spec.js index 6f8248e17d..a16a9e611e 100644 --- a/entry_types/scrolled/package/spec/frontend/EditableLink-spec.js +++ b/entry_types/scrolled/package/spec/frontend/EditableLink-spec.js @@ -2,91 +2,27 @@ import React from 'react'; import {EditableLink} from 'frontend'; -import {render} from '@testing-library/react'; import {renderInEntry} from 'support'; import '@testing-library/jest-dom/extend-expect' +// Link behavior is tested in Link-spec.js. +// These tests verify EditableLink correctly passes props to Link. + describe('EditableLink', () => { it('renders link', () => { - const {getByRole} = render( + const {getByRole} = renderInEntry( Some link ); expect(getByRole('link')).toHaveTextContent('Some link') expect(getByRole('link')).toHaveAttribute('href', 'https://example.com') - expect(getByRole('link')).not.toHaveAttribute('target') - expect(getByRole('link')).not.toHaveAttribute('rel') }); it('supports className', () => { - const {getByRole} = render( + const {getByRole} = renderInEntry( Some link ); expect(getByRole('link')).toHaveClass('custom') }); - - it('supports rendering link with target blank', () => { - const {getByRole} = render( - Some link - ); - - expect(getByRole('link')).toHaveTextContent('Some link') - expect(getByRole('link')).toHaveAttribute('target', '_blank') - expect(getByRole('link')).toHaveAttribute('rel', 'noopener noreferrer') - }); - - it('supports rendering internal chapter links', () => { - const seed = { - chapters: [{id: 1, permaId: 10, configuration: {title: 'The Intro'}}] - }; - - const {getByRole} = renderInEntry( - Some link, - {seed} - ); - - expect(getByRole('link')).toHaveTextContent('Some link') - expect(getByRole('link')).toHaveAttribute('href', '#the-intro') - expect(getByRole('link')).not.toHaveAttribute('target') - expect(getByRole('link')).not.toHaveAttribute('rel') - }); - - it('supports rendering internal section links', () => { - const seed = { - sections: [{id: 1, permaId: 10}] - }; - - const {getByRole} = renderInEntry( - Some link, - {seed} - ); - - expect(getByRole('link')).toHaveTextContent('Some link') - expect(getByRole('link')).toHaveAttribute('href', '#section-10') - expect(getByRole('link')).not.toHaveAttribute('target') - expect(getByRole('link')).not.toHaveAttribute('rel') - }); - - it('supports rendering file links', () => { - const seed = { - imageFileUrlTemplates: { - original: ':id_partition/original/:basename.:extension' - }, - sections: [{id: 1, permaId: 10}], - imageFiles: [{id: 1, permaId: 100, displayName: 'Some File.jpg'}] - }; - - const {getByRole} = renderInEntry( - - Some link - , - {seed} - ); - - expect(getByRole('link')).toHaveTextContent('Some link') - expect(getByRole('link')).toHaveAttribute('href', '000/000/001/original/image.jpg?download=Some%20File.jpg') - expect(getByRole('link')).toHaveAttribute('target', '_blank') - expect(getByRole('link')).toHaveAttribute('rel', 'noopener noreferrer') - }); }); diff --git a/entry_types/scrolled/package/spec/frontend/EditableTable-spec.js b/entry_types/scrolled/package/spec/frontend/EditableTable-spec.js index 3b8a6e597f..32411b32b7 100644 --- a/entry_types/scrolled/package/spec/frontend/EditableTable-spec.js +++ b/entry_types/scrolled/package/spec/frontend/EditableTable-spec.js @@ -4,6 +4,7 @@ import {EditableTable} from 'frontend'; import * as phoneLayout from 'frontend/usePhoneLayout'; import {render, screen} from '@testing-library/react'; +import {renderInEntry} from 'support'; import '@testing-library/jest-dom/extend-expect' describe('EditableTable', () => { @@ -74,7 +75,7 @@ describe('EditableTable', () => { ] }]; - const {getByRole} = render(); + const {getByRole} = renderInEntry(); expect(getByRole('link')).toHaveTextContent('here') expect(getByRole('link')).toHaveAttribute('href', 'https://example.com') @@ -111,7 +112,7 @@ describe('EditableTable', () => { ] }]; - const {getByRole} = render(); + const {getByRole} = renderInEntry(); expect(getByRole('link')).toHaveTextContent('here') expect(getByRole('link')).toHaveAttribute('target', '_blank') diff --git a/entry_types/scrolled/package/spec/frontend/EditableText-spec.js b/entry_types/scrolled/package/spec/frontend/EditableText-spec.js index 4f7f285a22..fc35025ae4 100644 --- a/entry_types/scrolled/package/spec/frontend/EditableText-spec.js +++ b/entry_types/scrolled/package/spec/frontend/EditableText-spec.js @@ -97,6 +97,9 @@ describe('EditableText', () => { expect(getByRole('listitem')).toHaveTextContent('List item') }); + // Link behavior is tested in Link-spec.js. + // These tests verify EditableText correctly renders links via Link. + it('renders links', () => { const value = [{ type: 'paragraph', @@ -113,37 +116,11 @@ describe('EditableText', () => { ] }] - const {getByRole} = render(); + const {getByRole} = renderInEntry(); expect(getByRole('link')).toHaveTextContent('here') expect(getByRole('link')).toHaveAttribute('href', 'https://example.com') expect(getByRole('link')).toHaveClass('typography-contentLink') - expect(getByRole('link')).not.toHaveAttribute('target') - expect(getByRole('link')).not.toHaveAttribute('rel') - }); - - it('supports rendering links with target blank', () => { - const value = [{ - type: 'paragraph', - children: [ - {text: 'Find more '}, - { - type: 'link', - href: 'https://example.com', - openInNewTab: true, - children: [ - {text: 'here'} - ] - }, - {text: '.'} - ] - }] - - const {getByRole} = render(); - - expect(getByRole('link')).toHaveTextContent('here') - expect(getByRole('link')).toHaveAttribute('target', '_blank') - expect(getByRole('link')).toHaveAttribute('rel', 'noopener noreferrer') }); it('supports rendering internal chapter links', () => { @@ -170,68 +147,6 @@ describe('EditableText', () => { expect(getByRole('link')).toHaveTextContent('here') expect(getByRole('link')).toHaveAttribute('href', '#the-intro') expect(getByRole('link')).toHaveClass('typography-contentLink') - expect(getByRole('link')).not.toHaveAttribute('target') - expect(getByRole('link')).not.toHaveAttribute('rel') - }); - - it('supports rendering internal section links', () => { - const value = [{ - type: 'paragraph', - children: [ - {text: 'Find more '}, - { - type: 'link', - href: {section: 10}, - children: [ - {text: 'here'} - ] - }, - {text: '.'} - ] - }]; - const seed = { - sections: [{id: 1, permaId: 10}] - }; - - const {getByRole} = renderInEntry(, {seed}); - - expect(getByRole('link')).toHaveTextContent('here') - expect(getByRole('link')).toHaveAttribute('href', '#section-10') - expect(getByRole('link')).toHaveClass('typography-contentLink') - expect(getByRole('link')).not.toHaveAttribute('target') - expect(getByRole('link')).not.toHaveAttribute('rel') - }); - - it('supports rendering file links', () => { - const value = [{ - type: 'paragraph', - children: [ - {text: 'Find more '}, - { - type: 'link', - href: {file: {permaId: 100, collectionName: 'imageFiles'}}, - children: [ - {text: 'here'} - ] - }, - {text: '.'} - ] - }]; - const seed = { - imageFileUrlTemplates: { - original: ':id_partition/original/:basename.:extension' - }, - sections: [{id: 1, permaId: 10}], - imageFiles: [{id: 1, permaId: 100, displayName: 'MyImage.jpg'}] - }; - - const {getByRole} = renderInEntry(, {seed}); - - expect(getByRole('link')).toHaveTextContent('here') - expect(getByRole('link')).toHaveAttribute('href', '000/000/001/original/image.jpg?download=MyImage.jpg') - expect(getByRole('link')).toHaveClass('typography-contentLink') - expect(getByRole('link')).toHaveAttribute('target', '_blank') - expect(getByRole('link')).toHaveAttribute('rel', 'noopener noreferrer') }); it('renders zero width no break space in empty leafs to prevent empty paragraphs from collapsing', () => { diff --git a/entry_types/scrolled/package/spec/frontend/Link-spec.js b/entry_types/scrolled/package/spec/frontend/Link-spec.js new file mode 100644 index 0000000000..67e62a1875 --- /dev/null +++ b/entry_types/scrolled/package/spec/frontend/Link-spec.js @@ -0,0 +1,140 @@ +import {Link} from 'frontend/Link'; + +import React from 'react'; + +import {renderInEntry} from 'support'; +import '@testing-library/jest-dom/extend-expect'; + +describe('Link', () => { + describe('with string href', () => { + it('does not set target by default', () => { + const {getByRole} = renderInEntry( + Click + ); + + expect(getByRole('link')).toHaveAttribute('href', 'http://example.com'); + expect(getByRole('link')).not.toHaveAttribute('target'); + }); + + it('sets target _blank when openInNewTab is true', () => { + const {getByRole} = renderInEntry( + Click + ); + + expect(getByRole('link')).toHaveAttribute('target', '_blank'); + }); + + describe('in embed mode', () => { + it('sets target _top for external link', () => { + const {getByRole} = renderInEntry( + Click, + { + seed: { + embed: true, + originUrl: 'http://example.com/my-entry' + } + } + ); + + expect(getByRole('link')).toHaveAttribute('target', '_top'); + }); + + it('does not set target for link starting with origin url', () => { + const {getByRole} = renderInEntry( + Click, + { + seed: { + embed: true, + originUrl: 'http://example.com/my-entry' + } + } + ); + + expect(getByRole('link')).not.toHaveAttribute('target'); + }); + + it('does not set target for fragment-only link', () => { + const {getByRole} = renderInEntry( + Click, + { + seed: { + embed: true, + originUrl: 'http://example.com/my-entry' + } + } + ); + + expect(getByRole('link')).not.toHaveAttribute('target'); + }); + + it('prefers openInNewTab over embed mode target', () => { + const {getByRole} = renderInEntry( + Click, + { + seed: { + embed: true, + originUrl: 'http://example.com/my-entry' + } + } + ); + + expect(getByRole('link')).toHaveAttribute('target', '_blank'); + }); + }); + }); + + describe('with chapter href', () => { + it('renders link to chapter slug', () => { + const {getByRole} = renderInEntry( + Click, + { + seed: { + chapters: [{id: 1, permaId: 10, configuration: {title: 'The Intro'}}] + } + } + ); + + expect(getByRole('link')).toHaveAttribute('href', '#the-intro'); + expect(getByRole('link')).not.toHaveAttribute('target'); + }); + }); + + describe('with section href', () => { + it('renders link to section anchor', () => { + const {getByRole} = renderInEntry( + Click, + { + seed: { + sections: [{id: 1, permaId: 10}] + } + } + ); + + expect(getByRole('link')).toHaveAttribute('href', '#section-10'); + expect(getByRole('link')).not.toHaveAttribute('target'); + }); + }); + + describe('with file href', () => { + it('renders download link with target blank', () => { + const {getByRole} = renderInEntry( + Click, + { + seed: { + imageFileUrlTemplates: { + original: ':id_partition/original/:basename.:extension' + }, + imageFiles: [{id: 1, permaId: 100, displayName: 'Some File.jpg'}] + } + } + ); + + expect(getByRole('link')).toHaveAttribute( + 'href', + '000/000/001/original/image.jpg?download=Some%20File.jpg' + ); + expect(getByRole('link')).toHaveAttribute('target', '_blank'); + expect(getByRole('link')).toHaveAttribute('rel', 'noopener noreferrer'); + }); + }); +}); diff --git a/entry_types/scrolled/package/src/entryState/embedOriginUrl.js b/entry_types/scrolled/package/src/entryState/embedOriginUrl.js new file mode 100644 index 0000000000..5222c70364 --- /dev/null +++ b/entry_types/scrolled/package/src/entryState/embedOriginUrl.js @@ -0,0 +1,6 @@ +import {useEntryStateConfig} from "./EntryStateProvider"; + +export function useEmbedOriginUrl() { + const config = useEntryStateConfig(); + return config.embed ? config.originUrl : undefined; +} diff --git a/entry_types/scrolled/package/src/entryState/index.js b/entry_types/scrolled/package/src/entryState/index.js index 2251a8aefb..18d6c47545 100644 --- a/entry_types/scrolled/package/src/entryState/index.js +++ b/entry_types/scrolled/package/src/entryState/index.js @@ -1,6 +1,7 @@ export {useAdditionalSeedData} from './additionalSeedData'; export {useContentElementConsentVendor} from './consentVendors'; export {useCutOff} from './cutoff'; +export {useEmbedOriginUrl} from './embedOriginUrl'; export {useShareProviders, useShareUrl} from './sharing'; export {useEntryTranslations} from './entryTranslations'; export { diff --git a/entry_types/scrolled/package/src/frontend/Link.js b/entry_types/scrolled/package/src/frontend/Link.js index 164870b782..ca1c14b9db 100644 --- a/entry_types/scrolled/package/src/frontend/Link.js +++ b/entry_types/scrolled/package/src/frontend/Link.js @@ -1,8 +1,10 @@ import React from 'react'; -import {useChapter, useDownloadableFile} from '../entryState'; +import {useChapter, useDownloadableFile, useEmbedOriginUrl} from '../entryState'; export function Link({attributes, children, href, openInNewTab}) { + const embedOriginUrl = useEmbedOriginUrl(); + if (href?.chapter) { return ( ; } + +function getTargetAttributes({href, openInNewTab, embedOriginUrl}) { + if (openInNewTab) { + return {target: '_blank', rel: 'noopener noreferrer'}; + } + + if (embedOriginUrl && + typeof href === 'string' && + !href.startsWith('#') && + !href.startsWith(embedOriginUrl)) { + return {target: '_top'}; + } + + return {}; +} diff --git a/entry_types/scrolled/package/src/testHelpers/normalizeSeed.js b/entry_types/scrolled/package/src/testHelpers/normalizeSeed.js index 66f8bee139..c4ebf1a808 100644 --- a/entry_types/scrolled/package/src/testHelpers/normalizeSeed.js +++ b/entry_types/scrolled/package/src/testHelpers/normalizeSeed.js @@ -49,6 +49,8 @@ export function normalizeSeed({ consentVendors, contentElementConsentVendors, cutOff, + embed, + originUrl, fileLicenses, entryTranslations } = {}) { @@ -96,6 +98,8 @@ export function normalizeSeed({ consentVendors: consentVendors || [], contentElementConsentVendors: contentElementConsentVendors || {}, cutOff, + embed, + originUrl, fileLicenses: fileLicenses || {}, entryTranslations: entryTranslations || [] }, diff --git a/entry_types/scrolled/spec/controllers/pageflow_scrolled/entries_controller_spec.rb b/entry_types/scrolled/spec/controllers/pageflow_scrolled/entries_controller_spec.rb index 720850e7fa..9939dcc17c 100644 --- a/entry_types/scrolled/spec/controllers/pageflow_scrolled/entries_controller_spec.rb +++ b/entry_types/scrolled/spec/controllers/pageflow_scrolled/entries_controller_spec.rb @@ -37,6 +37,31 @@ module PageflowScrolled expect(response.body).to have_selector('figcaption', text: 'Some caption') end + it 'server side renders external links with target top in embed mode' do + entry = create(:entry, :published, type_name: 'scrolled') + chapter = create(:scrolled_chapter, revision: entry.published_revision) + section = create(:section, chapter:) + create(:content_element, + section:, + type_name: 'textBlock', + configuration: { + value: [{ + type: 'paragraph', + children: [ + { + type: 'link', + href: 'https://example.com', + children: [{text: 'External link'}] + } + ] + }] + }) + + get_with_entry_env(:show, entry:, embed: true) + + expect(response.body).to have_selector('a[href="https://example.com"][target="_top"]') + end + it 'renders generated media queries if frontend v2' do entry = create(:entry, :published, type_name: 'scrolled') @@ -150,6 +175,30 @@ module PageflowScrolled expect(response.body).to have_selector('link[type="application/atom+xml"]', visible: false) end + + it 'includes embed false in seed data by default' do + entry = create(:entry, :published, type_name: 'scrolled') + + get_with_entry_env(:show, entry:) + + expect(response.body).to include('"embed":false') + end + + it 'includes embed true in seed data for embed requests' do + entry = create(:entry, :published, type_name: 'scrolled') + + get_with_entry_env(:show, entry:, embed: true) + + expect(response.body).to include('"embed":true') + end + + it 'includes origin_url in seed data' do + entry = create(:entry, :published, type_name: 'scrolled') + + get_with_entry_env(:show, entry:) + + expect(response.body).to include('"originUrl":"http://test.host/test/entry"') + end end end end diff --git a/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb b/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb index 6a8b169582..9ba604acb7 100644 --- a/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb +++ b/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb @@ -1408,6 +1408,46 @@ def render(helper, entry, options = {}) end end + context 'embed' do + it 'renders false by default' do + entry = create(:published_entry, + type_name: 'scrolled') + + result = render(helper, entry) + + expect(result).to include_json(config: {embed: false}) + end + + it 'renders true when embed option is true' do + entry = create(:published_entry, + type_name: 'scrolled') + + result = render(helper, entry, embed: true) + + expect(result).to include_json(config: {embed: true}) + end + end + + context 'origin_url' do + it 'is not rendered by default' do + entry = create(:published_entry, + type_name: 'scrolled') + + result = render(helper, entry) + + expect(JSON.parse(result)['config']).not_to have_key('originUrl') + end + + it 'renders origin_url when option is provided' do + entry = create(:published_entry, + type_name: 'scrolled') + + result = render(helper, entry, origin_url: 'https://example.com/my-entry') + + expect(result).to include_json(config: {originUrl: 'https://example.com/my-entry'}) + end + end + context 'cutoff' do it 'renders false by default' do entry = create(:published_entry, diff --git a/lib/pageflow/entries_controller_env_helper.rb b/lib/pageflow/entries_controller_env_helper.rb index 4cbefced89..89a5e270b9 100644 --- a/lib/pageflow/entries_controller_env_helper.rb +++ b/lib/pageflow/entries_controller_env_helper.rb @@ -28,9 +28,19 @@ def get_entry_mode_from_env(env = request.env) EntriesControllerEnvHelper.get_pageflow_hash(env)['entry_mode'] end + # Returns `true` if the entry is being rendered as an embed. The + # information will be placed in the request env by the Pageflow + # engine before delegating to the entry type's frontend app. + # + # Use {EntriesControllerTestHelper} to set up the request + # environment in controller tests. + def get_embed_from_env(env = request.env) + EntriesControllerEnvHelper.get_pageflow_hash(env)['embed'] + end + # @api private - def self.add_entry_info_to_env(env, entry:, mode: nil) - env['pageflow'] = {'published_entry' => entry, 'entry_mode' => mode} + def self.add_entry_info_to_env(env, entry:, mode: nil, embed: false) + env['pageflow'] = {'published_entry' => entry, 'entry_mode' => mode, 'embed' => embed} end # @api private diff --git a/spec/pageflow/entries_controller_env_helper_spec.rb b/spec/pageflow/entries_controller_env_helper_spec.rb index a37e3c8f1d..337818a811 100644 --- a/spec/pageflow/entries_controller_env_helper_spec.rb +++ b/spec/pageflow/entries_controller_env_helper_spec.rb @@ -37,5 +37,23 @@ module Pageflow }.to raise_error(/Use Pageflow::EntriesControllerTestHelper/) end end + + describe '#get_embed_from_env' do + it 'reads embed from where add_entry_info_to_env puts it' do + env = {} + entry = build(:entry) + + EntriesControllerEnvHelper.add_entry_info_to_env(env, entry:, embed: true) + result = EntriesControllerEnvHelper.get_embed_from_env(env) + + expect(result).to be(true) + end + + it 'fails with a helpful message when info is missing in env' do + expect { + EntriesControllerEnvHelper.get_embed_from_env({}) + }.to raise_error(/Use Pageflow::EntriesControllerTestHelper/) + end + end end end diff --git a/spec/requests/pageflow/entries_show_request_spec.rb b/spec/requests/pageflow/entries_show_request_spec.rb index fbcd89a61d..9b1297fe2a 100644 --- a/spec/requests/pageflow/entries_show_request_spec.rb +++ b/spec/requests/pageflow/entries_show_request_spec.rb @@ -6,10 +6,11 @@ module Pageflow lambda do |env| entry = EntriesControllerEnvHelper.get_published_entry_from_env(env) mode = EntriesControllerEnvHelper.get_entry_mode_from_env(env) + embed = EntriesControllerEnvHelper.get_embed_from_env(env) ['200', {'Content-Type' => 'text/html'}, - ["#{entry.title} #{mode} rendered by entry type frontend app."]] + ["#{entry.title} #{mode} embed=#{embed} rendered by entry type frontend app."]] end end @@ -59,7 +60,16 @@ module Pageflow get(short_entry_url(entry)) expect(response.status).to eq(200) - expect(response.body).to include('some-entry published rendered by entry type frontend app') + expect(response.body).to include('some-entry published embed=false rendered by entry type frontend app') + end + + it 'passes embed=true for embed requests' do + entry = create(:entry, :published, type_name: 'test', title: 'some-entry') + + get(entry_embed_url(entry)) + + expect(response.status).to eq(200) + expect(response.body).to include('some-entry published embed=true rendered by entry type frontend app') end it 'supports finding published entry based on permalink' do @@ -79,7 +89,7 @@ module Pageflow expect(response.status).to eq(200) expect(response.body) - .to include('some-entry published rendered by entry type frontend app') + .to include('some-entry published embed=false rendered by entry type frontend app') end it 'supports finding published entry based on permalink with directory' do @@ -100,7 +110,7 @@ module Pageflow expect(response.status).to eq(200) expect(response.body) - .to include('some-entry published rendered by entry type frontend app') + .to include('some-entry published embed=false rendered by entry type frontend app') end it 'redirects to renamed permalink' do @@ -227,7 +237,7 @@ module Pageflow get('http://my.example.com/non-existent-entry') expect(response.status).to eq(404) - expect(response.body).to include('Custom 404 published rendered by entry type frontend app') + expect(response.body).to include('Custom 404 published embed=false rendered by entry type frontend app') end it 'falls back to default 404 when site has no custom_404_entry' do diff --git a/spec/support/pageflow/entries_controller_test_helper.rb b/spec/support/pageflow/entries_controller_test_helper.rb index e8eed0d380..6197992f37 100644 --- a/spec/support/pageflow/entries_controller_test_helper.rb +++ b/spec/support/pageflow/entries_controller_test_helper.rb @@ -32,7 +32,10 @@ module EntriesControllerTestHelper # # @param mode [:published|:preview] Whether to render the # published revision or the draft. - def get_with_entry_env(action, entry:, mode: :published, params: {}) + # + # @param embed [Boolean] Whether the entry is being rendered as an + # embed. + def get_with_entry_env(action, entry:, mode: :published, embed: false, params: {}) revision = if mode == :published entry.published_revision @@ -43,7 +46,8 @@ def get_with_entry_env(action, entry:, mode: :published, params: {}) published_entry = PublishedEntry.new(entry, revision) EntriesControllerEnvHelper.add_entry_info_to_env(request.env, entry: published_entry, - mode:) + mode:, + embed:) get(action, params: {**params}) end end