Skip to content

Commit d458fc5

Browse files
authored
🐛 Fixed Unsplash integration not loading when selecting Publication Cover image (#26282)
ref https://linear.app/ghost/issue/ONC-1453/unsplash-integration-not-loading ## Problem In Admin Settings > Design and Branding, the unsplash selector for the Publication Cover isn't working properly. Rather than showing Unsplash images, it's just showing a blank white screen on the Unsplash modal. the Unsplash selector on the main Post editor is working fine. ## Diagnosis When loading the Unsplash selector for Publication Cover, the request to Unsplash returns a 401: Unauthorized error. Upon further inspection, the new React admin wrapper in apps/admin is supplying blank values for the unsplash configuration. ## Fix Supply the same unsplash configuration in apps/admin that we do in Ember admin.
1 parent 7c8d32b commit d458fc5

File tree

6 files changed

+64
-7
lines changed

6 files changed

+64
-7
lines changed

apps/admin-x-design-system/src/global/form/image-upload.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ const ImageUpload: React.FC<ImageUploadProps> = ({
127127

128128
if (imageURL) {
129129
let image = (
130-
<div className={imageContainerClassName} style={{
130+
<div className={imageContainerClassName} data-testid="image-upload-container" style={{
131131
width: (unstyled ? '' : width),
132132
height: (unstyled ? '' : height)
133133
}}>
@@ -142,7 +142,7 @@ const ImageUpload: React.FC<ImageUploadProps> = ({
142142
{editButtonContent}
143143
</button>
144144
}
145-
<button className={deleteButtonClassName} type='button' onClick={onDelete}>
145+
<button className={deleteButtonClassName} data-testid="image-delete-button" type='button' onClick={onDelete}>
146146
{deleteButtonContent}
147147
</button>
148148
</div>

apps/admin-x-settings/src/components/settings/site/design-and-branding/global-settings.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ const GlobalSettings: React.FC<{ values: GlobalSettingValues, updateSetting: (ke
255255
</ImageUpload>
256256
</div>
257257
</div>
258-
<div className='mt-2 flex items-start justify-between'>
258+
<div className='mt-2 flex items-start justify-between' data-testid="publication-cover">
259259
<div>
260260
<div>Publication cover</div>
261261
<Hint className='!mt-0 mr-5 max-w-[160px]'>Usually as a large banner image on your index pages</Hint>

apps/admin/src/main.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ const framework = {
1515
navigateTo(link.route);
1616
},
1717
unsplashConfig: {
18-
Authorization: "",
19-
"Accept-Version": "",
20-
"Content-Type": "",
21-
"App-Pragma": "",
18+
Authorization: "Client-ID 8672af113b0a8573edae3aa3713886265d9bb741d707f6c01a486cde8c278980",
19+
"Accept-Version": "v1",
20+
"Content-Type": "application/json",
21+
"App-Pragma": "no-cache",
2222
"X-Unsplash-Cache": true,
2323
},
2424
sentryDSN: null,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {BasePage} from '@/helpers/pages';
2+
import {Locator, Page} from '@playwright/test';
3+
4+
export class DesignSection extends BasePage {
5+
readonly section: Locator;
6+
readonly customizeButton: Locator;
7+
readonly designModal: Locator;
8+
readonly unsplashButton: Locator;
9+
readonly unsplashHeading: Locator;
10+
readonly coverImage: Locator;
11+
12+
constructor(page: Page) {
13+
super(page, '/ghost/#/settings');
14+
15+
this.section = page.getByTestId('design');
16+
this.customizeButton = this.section.getByRole('button', {name: 'Customize'});
17+
this.designModal = page.getByTestId('design-modal');
18+
this.unsplashButton = page.getByTestId('toggle-unsplash-button');
19+
this.unsplashHeading = page.getByRole('heading', {name: 'Unsplash', level: 1});
20+
this.coverImage = page.getByTestId('publication-cover');
21+
}
22+
23+
async openDesignModal(): Promise<void> {
24+
await this.customizeButton.click();
25+
await this.designModal.waitFor({state: 'visible'});
26+
}
27+
28+
async deleteCoverImage(): Promise<void> {
29+
const imageContainer = this.coverImage.getByTestId('image-upload-container');
30+
await imageContainer.hover();
31+
await imageContainer.getByTestId('image-delete-button').click();
32+
}
33+
34+
async openUnsplashSelector(): Promise<void> {
35+
await this.unsplashButton.click();
36+
await this.unsplashHeading.waitFor({state: 'visible'});
37+
}
38+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export {PublicationSection} from './publications-section';
22
export {LabsSection} from './labs-section';
33
export {IntegrationsSection} from './integrations-section';
4+
export {DesignSection} from './design-section';
45
export {MemberWelcomeEmailsSection} from './member-welcome-emails-section';
56
export {IntegrationModal, INTEGRATIONS} from './integration-modal';
67
export type {IntegrationConfig, IntegrationName} from './integration-modal';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {DesignSection} from '@/admin-pages';
2+
import {expect, test} from '@/helpers/playwright';
3+
4+
test.describe('Ghost Admin - Design & Branding', () => {
5+
test.describe('Unsplash Selector', () => {
6+
test('unsplash selector loads photos', async ({page}) => {
7+
const design = new DesignSection(page);
8+
9+
await design.goto();
10+
await design.openDesignModal();
11+
await design.deleteCoverImage();
12+
await design.openUnsplashSelector();
13+
14+
const unsplashPhoto = page.locator('[data-kg-unsplash-gallery-img]');
15+
await expect(unsplashPhoto.first()).toBeVisible({timeout: 10000});
16+
});
17+
});
18+
});

0 commit comments

Comments
 (0)