diff --git a/ghost/admin/app/components/gh-member-settings-form.hbs b/ghost/admin/app/components/gh-member-settings-form.hbs index 19e5622655..d7a4f28d49 100644 --- a/ghost/admin/app/components/gh-member-settings-form.hbs +++ b/ghost/admin/app/components/gh-member-settings-form.hbs @@ -66,7 +66,7 @@ {{#if this.canShowSingleNewsletter}} -
+

Subscribed to newsletter

If disabled, member will not receive newsletter emails

diff --git a/ghost/admin/app/components/member/newsletter-preference.hbs b/ghost/admin/app/components/member/newsletter-preference.hbs index 81fc6cabc3..75c709323a 100644 --- a/ghost/admin/app/components/member/newsletter-preference.hbs +++ b/ghost/admin/app/components/member/newsletter-preference.hbs @@ -3,7 +3,7 @@ {{#unless this.suppressionData.suppressed}}
{{#each this.newsletters as |newsletter|}} -
+

{{newsletter.name}}

diff --git a/ghost/admin/app/components/modals/newsletters/new.hbs b/ghost/admin/app/components/modals/newsletters/new.hbs index 9a9cde61e4..ac30f0f37b 100644 --- a/ghost/admin/app/components/modals/newsletters/new.hbs +++ b/ghost/admin/app/components/modals/newsletters/new.hbs @@ -14,6 +14,7 @@ class="gh-input miw-100 form-text" value={{@data.newsletter.name}} placeholder="Weekly Roundup" + data-test-newsletter-title-input {{on "input" (fn this.onInput "name")}} /> diff --git a/ghost/admin/app/templates/settings.hbs b/ghost/admin/app/templates/settings.hbs index c84048fbd9..8e7e093f07 100644 --- a/ghost/admin/app/templates/settings.hbs +++ b/ghost/admin/app/templates/settings.hbs @@ -68,7 +68,7 @@
{{#if (feature 'sourceAttribution')}} - + {{svg-jar "chart"}}

Analytics

diff --git a/ghost/core/test/e2e-browser/portal/member-actions.spec.js b/ghost/core/test/e2e-browser/portal/member-actions.spec.js new file mode 100644 index 0000000000..85e8a9aa65 --- /dev/null +++ b/ghost/core/test/e2e-browser/portal/member-actions.spec.js @@ -0,0 +1,133 @@ +const {expect, test} = require('@playwright/test'); +const {createMember, impersonateMember} = require('../utils'); + +const addNewsletter = async (page) => { + // go to email settings + await page.goto('/ghost'); + await page.locator('[data-test-nav="settings"]').click(); + await page.locator('[data-test-nav="members-email"]').click(); + + // create newsletter + await page.locator('[data-test-button="add-newsletter"]').click(); + await page.locator('[data-test-newsletter-title-input]').click(); + await page.locator('[data-test-newsletter-title-input]').fill('One more newsletter'); + await page.locator('[data-test-button="save-newsletter"]').click(); + + // check that newsletter was added + await page.waitForSelector('[data-test-newsletter="one-more-newsletter"]'); +}; + +test.describe('Portal', () => { + test.describe('Member actions', () => { + test('can log out', async ({page}) => { + // create a new free member + await createMember(page, { + name: 'Test Member Signout', + email: 'test.member.signout@example.com', + note: 'Test Member' + }); + + // impersonate the member on frontend + impersonateMember(page); + + const portalTriggerButton = page.frameLocator('#ghost-portal-root iframe.gh-portal-triggerbtn-iframe').locator('div').nth(1); + const portalFrame = page.frameLocator('#ghost-portal-root div iframe'); + + // sign out + await portalTriggerButton.click(); + await portalFrame.locator('[data-test-button="footer-signout"]').click(); + + // check that sign out was successful and 'Sign in' button is available + await portalTriggerButton.click(); + await expect(portalFrame.locator('[data-test-button="signin-switch"]')).toBeVisible(); + }); + + test('can unsubscribe from newsletter from account settings', async ({page}) => { + // create a new free member + await createMember(page, { + name: 'Test Member', + email: 'test.member@example.com', + note: 'Test Member' + }); + //get the url of the current member on admin + const memberUrl = page.url(); + + // impersonate the member on frontend + impersonateMember(page); + + const portalTriggerButton = await page.locator('#gh-head').getByRole('link', {name: 'Account'}); + const portalFrame = page.frameLocator('#ghost-portal-root div iframe'); + + // open portal and turn off newsletter + await portalTriggerButton.click(); + + // todo: replace on data attr + expect(await portalFrame.locator('#default-newsletter-toggle').isChecked()).toBeTruthy(); + await portalFrame.locator('.gh-portal-for-switch .switch').click(); + expect(await portalFrame.locator('#default-newsletter-toggle').isChecked()).not.toBeTruthy(); + + // check that member's newsletters was updated in Admin + await page.goto(memberUrl); + expect(await page.locator('[data-test-member-settings-switch] input[type=checkbox]').first().isChecked()).not.toBeTruthy(); + }); + + test('can unsubscribe from all newsletters from account settings', async ({page}) => { + // create a new free member + await createMember(page, { + name: 'Test Member All Unsubscribe', + email: 'test.member2@example.com', + note: 'Test Member' + }); + // get the url of the current member on admin + const memberUrl = page.url(); + + await addNewsletter(page); + + // impersonate the member on frontend + await page.goto(memberUrl); + impersonateMember(page); + + const portalTriggerButton = await page.locator('#gh-head').getByRole('link', {name: 'Account'}); + const portalFrame = page.frameLocator('#ghost-portal-root div iframe'); + + // open portal + await portalTriggerButton.click(); + await portalFrame.locator('[data-test-button="manage-newsletters"]').click(); + + // check amount of newsletters + + // todo: replace on data attr + const newsletters = await portalFrame.locator('.gh-portal-list-toggle-wrapper'); + const count = await newsletters.count(); + expect(count).toEqual(2); + + // all newsletters should be activated + for (let i = 0; i < count; i++) { + expect(await newsletters.nth(i).locator('input[type="checkbox"]').isChecked()).toBeTruthy(); + } + + // unsubscribe from all emails + // todo: replace on data attr + await portalFrame.getByRole('button', {name: 'Unsubscribe from all emails'}).click(); + + // all newsletters should be disabled + for (let i = 0; i < count; i++) { + expect(await newsletters.nth(i).locator('input[type="checkbox"]').isChecked()).not.toBeTruthy(); + } + + // check that member's newsletters was updated in Admin + await page.goto(memberUrl); + + // check amount of newsletters in member's profile in Admin + await page.waitForSelector('[data-test-member-settings-switch]'); + const membersNewsletters = await page.locator('[data-test-member-settings-switch]'); + const newslettersCount = await membersNewsletters.count(); + expect(newslettersCount).toEqual(2); + + // all newsletters should be disabled + for (let i = 0; i < newslettersCount; i++) { + expect(await membersNewsletters.nth(i).locator('input[type="checkbox"]').isChecked()).not.toBeTruthy(); + } + }); + }); +});