diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/collections.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/collections.test.js.snap index c7747b2ec6a2..8c24463095ad 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/collections.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/collections.test.js.snap @@ -207,7 +207,7 @@ exports[`Collections API Automatic Collection Filtering Creates an automatic Col Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "12653", + "content-length": "12649", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -728,7 +728,7 @@ exports[`Collections API Automatic Collection Filtering Creates an automatic Col Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "78564", + "content-length": "78560", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -987,7 +987,7 @@ exports[`Collections API Automatic Collection Filtering Creates an automatic Col Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "14427", + "content-length": "14423", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1246,7 +1246,7 @@ exports[`Collections API Automatic Collection Filtering Creates an automatic Col Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "14427", + "content-length": "14423", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap index 23a80d62ff18..dc329b91d45b 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap @@ -381,7 +381,7 @@ exports[`Members API - member attribution Returns sign up attributions of all ty Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "8054", + "content-length": "8053", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap index 9af3952e41c2..fd6baad54e9f 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap @@ -647,7 +647,7 @@ exports[`Pages API Convert can convert a mobiledoc page to lexical 2: [headers] Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4065", + "content-length": "4063", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -753,7 +753,7 @@ exports[`Pages API Convert can convert a mobiledoc page to lexical 4: [headers] Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4065", + "content-length": "4063", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -947,7 +947,7 @@ exports[`Pages API Copy Can copy a page 3: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3859", + "content-length": "3857", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1053,7 +1053,7 @@ exports[`Pages API Create Can create a page with html 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4089", + "content-length": "4087", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1333,7 +1333,7 @@ exports[`Pages API Update Access Visibility is set to tiers Saves only paid tier Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3494", + "content-length": "3492", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1438,7 +1438,7 @@ exports[`Pages API Update Can modify show_title_and_feature_image property 2: [h Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3860", + "content-length": "3858", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/posts.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/posts.test.js.snap index dceba661f65e..3e90545e5160 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/posts.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/posts.test.js.snap @@ -197,7 +197,7 @@ exports[`Posts API Can browse 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "10736", + "content-length": "10732", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -421,7 +421,7 @@ exports[`Posts API Can browse filtering by a collection 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "11731", + "content-length": "11727", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -766,7 +766,7 @@ exports[`Posts API Can browse with formats 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "13534", + "content-length": "13530", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -874,7 +874,7 @@ exports[`Posts API Convert can convert a mobiledoc post to lexical 2: [headers] Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4102", + "content-length": "4100", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -983,7 +983,7 @@ exports[`Posts API Convert can convert a mobiledoc post to lexical 4: [headers] Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4102", + "content-length": "4100", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1089,7 +1089,7 @@ exports[`Posts API Copy Can copy a post 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3894", + "content-length": "3892", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1198,7 +1198,7 @@ exports[`Posts API Create Can create a post with html 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4124", + "content-length": "4122", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1307,7 +1307,7 @@ exports[`Posts API Create Can create a post with lexical 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4136", + "content-length": "4134", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1416,7 +1416,7 @@ exports[`Posts API Create Can create a post with mobiledoc 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3952", + "content-length": "3950", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1703,7 +1703,7 @@ exports[`Posts API Delete Can delete posts belonging to a collection and returns Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "11731", + "content-length": "11727", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2054,7 +2054,7 @@ exports[`Posts API Update Access Visibility is set to tiers Saves only paid tier Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3527", + "content-length": "3525", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2161,7 +2161,7 @@ exports[`Posts API Update Can add and remove collections 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3908", + "content-length": "3906", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2384,7 +2384,7 @@ exports[`Posts API Update Can add and remove collections 4: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "5504", + "content-length": "5502", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2607,7 +2607,7 @@ exports[`Posts API Update Can add and remove collections 6: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "5498", + "content-length": "5496", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2716,7 +2716,7 @@ exports[`Posts API Update Can update a post with lexical 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4087", + "content-length": "4085", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2825,7 +2825,7 @@ exports[`Posts API Update Can update a post with lexical 4: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4084", + "content-length": "4082", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2934,7 +2934,7 @@ exports[`Posts API Update Can update a post with mobiledoc 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3897", + "content-length": "3895", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -3043,7 +3043,7 @@ exports[`Posts API Update Can update a post with mobiledoc 4: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3894", + "content-length": "3892", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/session.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/session.test.js.snap index 7a43819c7aa6..1b6a4e31cc65 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/session.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/session.test.js.snap @@ -48,7 +48,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -67,7 +67,7 @@ exports[`Sessions API can read session now the owner is logged in 2: [headers] 1 Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "803", + "content-length": "802", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/core/test/e2e-api/members/webhooks.test.js b/ghost/core/test/e2e-api/members/webhooks.test.js index a0089d8a42d0..e3457796ca85 100644 --- a/ghost/core/test/e2e-api/members/webhooks.test.js +++ b/ghost/core/test/e2e-api/members/webhooks.test.js @@ -289,7 +289,7 @@ describe('Members API', function () { // Set the subscription to cancel at the end of the period set(subscription, { ...subscription, - status: 'active', + canceled_at: Date.now() / 1000, cancel_at_period_end: true, metadata: { cancellation_reason: 'I want to break free' @@ -353,7 +353,18 @@ describe('Members API', function () { ] }); - canceledPaidMember = updatedMember; + // Check that the staff notifications has been sent + await DomainEvents.allSettled(); + + mockManager.assert.sentEmail({ + subject: /Paid subscription started: Cancel me at the end of the billing cycle/, + to: 'jbloggs@example.com' + }); + + mockManager.assert.sentEmail({ + subject: /Cancellation: Cancel me at the end of the billing cycle/, + to: 'jbloggs@example.com' + }); }); it('Handles immediate cancellation of paid subscriptions', async function () { @@ -425,6 +436,7 @@ describe('Members API', function () { set(subscription, { ...subscription, status: 'canceled', + canceled_at: Date.now() / 1000, cancellation_details: { reason: 'payment_failed' } @@ -507,6 +519,19 @@ describe('Members API', function () { ] }); + // Check that the staff notifications has been sent + await DomainEvents.allSettled(); + + mockManager.assert.sentEmail({ + subject: /Paid subscription started: Cancel me now/, + to: 'jbloggs@example.com' + }); + + mockManager.assert.sentEmail({ + subject: /Cancellation: Cancel me now/, + to: 'jbloggs@example.com' + }); + canceledPaidMember = updatedMember; }); diff --git a/ghost/core/test/e2e-webhooks/__snapshots__/pages.test.js.snap b/ghost/core/test/e2e-webhooks/__snapshots__/pages.test.js.snap index 7da288e7d4da..a52e57c2b0f8 100644 --- a/ghost/core/test/e2e-webhooks/__snapshots__/pages.test.js.snap +++ b/ghost/core/test/e2e-webhooks/__snapshots__/pages.test.js.snap @@ -33,7 +33,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -86,7 +86,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -190,7 +190,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -270,7 +270,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -338,7 +338,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -492,7 +492,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -560,7 +560,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -714,7 +714,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -782,7 +782,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -935,7 +935,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1003,7 +1003,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1156,7 +1156,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1224,7 +1224,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1378,7 +1378,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1446,7 +1446,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1644,7 +1644,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1712,7 +1712,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1850,7 +1850,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1918,7 +1918,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -2071,7 +2071,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -2139,7 +2139,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, diff --git a/ghost/core/test/e2e-webhooks/__snapshots__/posts.test.js.snap b/ghost/core/test/e2e-webhooks/__snapshots__/posts.test.js.snap index 0ffa5816c5fb..8620e388510d 100644 --- a/ghost/core/test/e2e-webhooks/__snapshots__/posts.test.js.snap +++ b/ghost/core/test/e2e-webhooks/__snapshots__/posts.test.js.snap @@ -33,7 +33,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -89,7 +89,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -192,7 +192,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -271,7 +271,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -341,7 +341,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -493,7 +493,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -584,7 +584,7 @@ Header Level 3 "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -738,7 +738,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -808,7 +808,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -960,7 +960,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1030,7 +1030,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1182,7 +1182,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1252,7 +1252,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1405,7 +1405,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1496,7 +1496,7 @@ Header Level 3 "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1694,7 +1694,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1785,7 +1785,7 @@ Header Level 3 "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -1923,7 +1923,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -2014,7 +2014,7 @@ Header Level 3 "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -2167,7 +2167,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -2237,7 +2237,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "Joe Bloggs", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, diff --git a/ghost/core/test/regression/api/admin/__snapshots__/authentication.test.js.snap b/ghost/core/test/regression/api/admin/__snapshots__/authentication.test.js.snap index 825e3e030b67..3c8192c98b9b 100644 --- a/ghost/core/test/regression/api/admin/__snapshots__/authentication.test.js.snap +++ b/ghost/core/test/regression/api/admin/__snapshots__/authentication.test.js.snap @@ -594,7 +594,7 @@ Object { "meta_title": null, "milestone_notifications": true, "name": "test user edit", - "paid_subscription_canceled_notification": false, + "paid_subscription_canceled_notification": true, "paid_subscription_started_notification": true, "profile_image": "https://example.com/super_photo.jpg", "recommendation_notifications": true, @@ -614,7 +614,7 @@ exports[`Authentication API Blog setup update setup 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "794", + "content-length": "793", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/core/test/utils/fixtures/data-generator.js b/ghost/core/test/utils/fixtures/data-generator.js index be1a079d808d..b1c5997acb70 100644 --- a/ghost/core/test/utils/fixtures/data-generator.js +++ b/ghost/core/test/utils/fixtures/data-generator.js @@ -133,7 +133,8 @@ DataGenerator.Content = { slug: 'joe-bloggs', email: 'jbloggs@example.com', password: 'Sl1m3rson99', - profile_image: 'https://example.com/super_photo.jpg' + profile_image: 'https://example.com/super_photo.jpg', + paid_subscription_canceled_notification: true }, { // admin diff --git a/ghost/member-events/lib/SubscriptionCancelledEvent.js b/ghost/member-events/lib/SubscriptionCancelledEvent.js index 184a4399bfa9..81fa42222797 100644 --- a/ghost/member-events/lib/SubscriptionCancelledEvent.js +++ b/ghost/member-events/lib/SubscriptionCancelledEvent.js @@ -4,6 +4,9 @@ * @prop {string} memberId * @prop {string} tierId * @prop {string} subscriptionId + * @prop {boolean} cancelNow + * @prop {Date} expiryAt + * @prop {Date} canceledAt */ module.exports = class SubscriptionCancelledEvent { diff --git a/ghost/members-api/lib/repositories/MemberRepository.js b/ghost/members-api/lib/repositories/MemberRepository.js index 63f6e7de1d38..c2830940f85b 100644 --- a/ghost/members-api/lib/repositories/MemberRepository.js +++ b/ghost/members-api/lib/repositories/MemberRepository.js @@ -1066,7 +1066,7 @@ module.exports = class MemberRepository { const originalMrrDelta = model.get('mrr'); const updatedMrrDelta = updated.get('mrr'); - const getEventName = (originalStatus, updatedStatus) => { + const getEventType = (originalStatus, updatedStatus) => { if (originalStatus === updatedStatus) { return 'updated'; } @@ -1080,12 +1080,14 @@ module.exports = class MemberRepository { const originalStatus = getStatus(model); const updatedStatus = getStatus(updated); + const eventType = getEventType(originalStatus, updatedStatus); const mrrDelta = updatedMrrDelta - originalMrrDelta; + await this._MemberPaidSubscriptionEvent.add({ member_id: member.id, source: 'stripe', - type: getEventName(originalStatus, updatedStatus), + type: eventType, subscription_id: updated.id, from_plan: model.get('plan_id'), to_plan: updated.get('status') === 'canceled' ? null : updated.get('plan_id'), @@ -1110,6 +1112,29 @@ module.exports = class MemberRepository { }); this.dispatchEvent(event, options); } + + // Dispatch cancellation event, i.e. send paid cancellation staff notification, if: + // 1. The subscription has been set to cancel at period end, by the member in Portal, status 'canceled' + // 2. The subscription has been immediately canceled (e.g. due to multiple failed payments), status 'expired' + if (this.isActiveSubscriptionStatus(originalStatus) && (updatedStatus === 'canceled' || updatedStatus === 'expired')) { + const context = options?.context || {}; + const source = this._resolveContextSource(context); + const cancelNow = updatedStatus === 'expired'; + const canceledAt = new Date(subscription.canceled_at * 1000); + const expiryAt = cancelNow ? canceledAt : updated.get('current_period_end'); + + const event = SubscriptionCancelledEvent.create({ + source, + tierId: ghostProduct?.get('id'), + memberId: member.id, + subscriptionId: updated.get('id'), + cancelNow, + canceledAt, + expiryAt + }); + + this.dispatchEvent(event, options); + } } } else { eventData.created_at = new Date(subscription.start_date * 1000); @@ -1456,34 +1481,6 @@ module.exports = class MemberRepository { id: member.id, subscription: updatedSubscription }, options); - - // Dispatch cancellation event - if (data.subscription.cancel_at_period_end) { - const stripeProductId = _.get(updatedSubscription, 'items.data[0].price.product'); - - let ghostProduct; - try { - ghostProduct = await this._productRepository.get( - {stripe_product_id: stripeProductId}, - {...sharedOptions, forUpdate: true} - ); - } catch (e) { - ghostProduct = null; - } - - const context = options?.context || {}; - const source = this._resolveContextSource(context); - const cancellationTimestamp = updatedSubscription.canceled_at - ? new Date(updatedSubscription.canceled_at * 1000) - : new Date(); - const cancelEventData = { - source, - memberId: member.id, - subscriptionId: subscriptionModel.get('id'), - tierId: ghostProduct?.get('id') - }; - this.dispatchEvent(SubscriptionCancelledEvent.create(cancelEventData, cancellationTimestamp), options); - } } } diff --git a/ghost/staff-service/lib/StaffService.js b/ghost/staff-service/lib/StaffService.js index 24e67e4d21c6..02d4e1b4dd78 100644 --- a/ghost/staff-service/lib/StaffService.js +++ b/ghost/staff-service/lib/StaffService.js @@ -119,11 +119,11 @@ class StaffService { attribution }); } else if (type === SubscriptionCancelledEvent) { - subscription.canceledAt = event.timestamp; await this.emails.notifyPaidSubscriptionCanceled({ member, tier, - subscription + subscription, + ...event.data }); } } diff --git a/ghost/staff-service/lib/StaffServiceEmails.js b/ghost/staff-service/lib/StaffServiceEmails.js index abb272ea902c..b107af3ee10f 100644 --- a/ghost/staff-service/lib/StaffServiceEmails.js +++ b/ghost/staff-service/lib/StaffServiceEmails.js @@ -122,7 +122,7 @@ class StaffServiceEmails { } } - async notifyPaidSubscriptionCanceled({member, tier, subscription}, options = {}) { + async notifyPaidSubscriptionCanceled({member, tier, subscription, cancelNow, expiryAt, canceledAt}, options = {}) { const users = await this.models.User.getEmailAlertUsers('paid-canceled', options); for (const user of users) { @@ -140,8 +140,9 @@ class StaffServiceEmails { }; const subscriptionData = { - expiryAt: this.getFormattedDate(subscription.cancelAt), - canceledAt: this.getFormattedDate(subscription.canceledAt), + expiryAt: this.getFormattedDate(expiryAt), + cancelNow: cancelNow, + canceledAt: this.getFormattedDate(canceledAt), cancellationReason: subscription.cancellationReason || '' }; diff --git a/ghost/staff-service/lib/email-templates/new-paid-cancellation.hbs b/ghost/staff-service/lib/email-templates/new-paid-cancellation.hbs index 40e4e67cdecb..3a44cff1197b 100644 --- a/ghost/staff-service/lib/email-templates/new-paid-cancellation.hbs +++ b/ghost/staff-service/lib/email-templates/new-paid-cancellation.hbs @@ -19,7 +19,7 @@ {{#if subscriptionData.cancellationReason}} Reason: {{subscriptionData.cancellationReason}} {{else}} - A paid member has just canceled their subscription. + A paid member's subscription has just been canceled. {{/if}} {{/inline}} {{/preview}} @@ -33,7 +33,7 @@
Hey there,
-A paid member has just canceled their subscription.
+A paid member's subscription has just been canceled.
Subscription expired on
+ {{else}}Subscription will expire on
+ {{/if}}{{subscriptionData.expiryAt}}