refs
https://www.notion.so/ghost/Marketing-Milestone-email-campaigns-1d2c9dee3cfa4029863edb16092ad5c4?pvs=4
- When milestones will be activated we would send out emails to users
that are way above the achieved milestone, as we didn't record
milestones before
- The plan is to implement a 0 milestone and don't send an email for
achieving those and also add all achieved milestones in the first run
until a first milestone is stored in the DB, then increment from there.
- This change takes care of two cases:
1. Milestones gets enabled and runs initially. We don't want to send
emails unless there's already at least one milestone achieved. For that
we add a 0 milestone helper and add a `initial` reason to the meta
object for the milestone event, so we can choose not to ping Slack and
also disable email sending for all milestones achieved in this initial
run.
2. All achieved milestones will be stored in the DB, even when that
means we skip some. This introduces the `skipped` reason which also
doesn't send emails for the skipped milestones, but will do for
correctly achieved milestones (always the highest one).
- Added handling for slack notifications to not attempt sending when
reason is `skipped` or `initial`
The service.js files are rarely unit tested because they are
essentially glue code which acts as a singleton and doesn't use
dependency injection, this lil cocktail makes it difficult to stub
dependencies, as well as to call the init method more than once in a
test suite. This change should give us improved unit test coverage
no issue
The Stripe Mocker mocks the Stripe API in memory, to make it much easier
to test subscription flows. Currently it is more a POC to see if it
works well. It probably needs a bit more work to support more scenarios.
- Added new tests for the subscription stats endpoint for 3D secure +
free trial flows using the new Stripe Mocker
- Updated members admin api tests to use Stripe Mocker (+ added new test
for deleting members with Stripe cancellation)
- Some tests called mockStripe at the beginning, but that method did
nothing apart from disabling network (which is the default now), then
they mocked Stripe inside the tests file... so I've removed those
because those conflict with the new mocker that is enabled when calling
mockStripe. We'll need to port those over later.
fixes https://github.com/TryGhost/Team/issues/2607
When a free trial converts to a paid subscription, and increases the MRR, it just creates a 'updated' paid subscription event.
To fix this, we need to count updated events that didn't change plan but do have a positive MRR. As an extension we could also check if the MRR change matches the expected MRR for the corresponsing Stripe plan, but that requires a more complex condition check (because for yearly subscriptions we need to convert to monthly), I don't think that is required here.
fixes https://github.com/TryGhost/Team/issues/2644
A 3D secure payment first has a status of incomplete, then active.
With the current logic, this creates 2 MemberPaidSubscriptionEvents:
- `created` with mrr_delta of 0
- `active` with mrr_delta of 5
We need to also count 'active' events. And to complement that, also 'inactive' events to make sure we balance out in rare cases.
refs https://github.com/TryGhost/Team/issues/2489
- adds attribution title and url for new free members and paid subscriptions to email alert
---------
Co-authored-by: Peter Zimon <peter.zimon@gmail.com>
- this cleans up all imports or variables that aren't currently being used
- this really helps keep the tests clean by only allowing what is needed
- I've left `should` as an exemption for now because we need to clean up
how it is used
- this is generally an anti-pattern in tests and leads to flaky
behaviour when tests are ran on different machines/loads
- this is currently unused so it is an easy removal
- we have our own class in order to add the `hasRegisteredListener`
function
- this commit refactors the implementation to use the class syntactic
sugar, which means we get better editor autocomplete
- this shouldn't change the functionality
fixes https://github.com/TryGhost/Team/issues/2560
When an email fails, and you reschedule the post, the error dialog was
shown (from the previous try). The retry button on that page allowed you
to retry sending the email immediately, which could be very confusing.
- The email error dialog is no longer shown for scheduled emails
- The email status is no longer polled for scheduled emails
- Retrying an email is not possible via the API if the post status is
not published or sent
- Added some extra snapshot tests
- When retrying an email, we immediately update the email status to
'pending' to have a better API response (instead of still returning
failed).
- Disabled email sending retrying in development (otherwise very hard to
test failed emails if it takes 10 mins before it gives up automatic
retrying)
closes https://github.com/TryGhost/Team/issues/2531
This commit fixes the issue where non-canonical URLs are included in the
XML sitemap, leading to poor SEO for our user's sites. The solution
implemented is to exclude any page or post that specifies a canonical
URL in its metadata from the sitemap.
To achieve this, a condition has been added to the 'addUrl' method,
which checks for the existence of a canonical URL in the metadata of the
resource being added to the sitemap. If a canonical URL is present, the
resource is excluded from the sitemap.
With this fix, our user's sites will have better SEO and improved search
engine visibility.
fixes https://github.com/TryGhost/Team/issues/2666
- Somehow occurrences of `&map_` got replaced with `↦`
- Disables escaping &, ', " and other HTML characters when not needed
(escaping is already handled by mobiledoc/lexical)
- Bumps unit test coverage of link replacer to 100%
no issue
- Nock doesn't support multiple calls to enableNetConnect -> only the last one counts. This fixes that issue.
- Some tests interacted directly with nock instead of using the mockManager to restore everything.
no issue
- vscode started adding warnings to all uses of decorators in Admin which was rather annoying
- added `jsconfig.json` with the necessary compiler options and an exclude list to keep performance happy
refs https://github.com/TryGhost/Toolbox/issues/524
- The "tableName" property is not present on the bookshelf model instance - it was a mistake assumption using it for logs. In case the logs are too ambiguous we could figure pass around model names separately into the "inlineSimpleFields" method
refs https://github.com/TryGhost/Toolbox/issues/524
- Mobiledoc from a migrated content could contain html/markdown cards that could have a variety of different resource <> url pairs. To avoid complex logic and parsing html/md going with a simplest approach - matching external content URLs purely based on provided domains. This gives useful enough of a tool to migrate external content for a specific service (e.g Revue)
- In cases where the content is not supported the fetching will fail with a message and move on to the next match - which is a reasonable behavior for a migration tool
refs https://github.com/TryGhost/Toolbox/issues/524
- Fetching media from a remote server is an expensive network operation. Given there's probability for the content to reuse the same image in different posts or in multiple places, we could save on extra fetches by adding caching to the remote media fetch method
https://github.com/TryGhost/Toolbox/issues/523
- During import process of content files the files from the root directory were also copied over. This is causing chaos in the root of content folder with files that only needed for data import. For example, the csv files needed for Revue import were also copied over by "file importer" even though those do not belong to any content.
- Any content import files - images, media, files, should be in according folders in the imported zip file. The root files in the base zip directory are for data-related imports