Left join active subscriptions of a newsletter email to get the right count

This commit is contained in:
Hongbo Wu
2023-01-18 14:37:54 +08:00
parent e94f6de466
commit f01ab3805a
4 changed files with 129 additions and 57 deletions

View File

@ -111,7 +111,7 @@ export const unsubscribeResolver = authorized<
}
}
const unsubscribed = await unsubscribe(subscription)
await unsubscribe(subscription)
analytics.track({
userId: uid,
@ -124,8 +124,8 @@ export const unsubscribeResolver = authorized<
return {
subscription: {
...unsubscribed,
newsletterEmail: unsubscribed.newsletterEmail.address,
...subscription,
newsletterEmail: subscription.newsletterEmail.address,
},
}
} catch (error) {

View File

@ -1,7 +1,10 @@
import { NewsletterEmail } from '../entity/newsletter_email'
import { nanoid } from 'nanoid'
import { User } from '../entity/user'
import { CreateNewsletterEmailErrorCode } from '../generated/graphql'
import {
CreateNewsletterEmailErrorCode,
SubscriptionStatus,
} from '../generated/graphql'
import { env } from '../env'
import { getRepository } from '../entity/utils'
import addressparser = require('nodemailer/lib/addressparser')
@ -38,11 +41,20 @@ export const createNewsletterEmail = async (
export const getNewsletterEmails = async (
userId: string
): Promise<NewsletterEmail[]> => {
return getRepository(NewsletterEmail).find({
where: { user: { id: userId } },
order: { createdAt: 'DESC' },
relations: ['user', 'subscriptions'],
})
return getRepository(NewsletterEmail)
.createQueryBuilder('newsletter_email')
.leftJoinAndSelect('newsletter_email.user', 'user')
.leftJoinAndSelect(
'newsletter_email.subscriptions',
'subscriptions',
'subscriptions.status = :status',
{
status: SubscriptionStatus.Active,
}
)
.where('newsletter_email.user_id = :userId', { userId })
.orderBy('newsletter_email.createdAt', 'DESC')
.getMany()
}
export const deleteNewsletterEmail = async (id: string): Promise<boolean> => {

View File

@ -15,7 +15,6 @@ import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
import { SubscriptionStatus } from '../src/generated/graphql'
import { Integration } from '../src/entity/integration'
import { FindOptionsWhere } from 'typeorm'
import { ContentDisplayReport } from '../src/entity/reports/content_display_report'
const runMigrations = async () => {
const migrationDirectory = __dirname + '/../../db/migrations'
@ -198,12 +197,13 @@ export const createTestLabel = async (
export const createTestSubscription = async (
user: User,
name: string,
newsletterEmail: NewsletterEmail
newsletterEmail: NewsletterEmail,
status = SubscriptionStatus.Active
): Promise<Subscription> => {
return getRepository(Subscription).save({
user,
name,
status: SubscriptionStatus.Active,
status,
newsletterEmail: { id: newsletterEmail.id },
})
}

View File

@ -9,13 +9,16 @@ import { generateFakeUuid, graphqlRequest, request } from '../util'
import { NewsletterEmail } from '../../src/entity/newsletter_email'
import { User } from '../../src/entity/user'
import { expect } from 'chai'
import { DeleteNewsletterEmailErrorCode } from '../../src/generated/graphql'
import {
DeleteNewsletterEmailErrorCode,
SubscriptionStatus,
} from '../../src/generated/graphql'
import 'mocha'
import { getRepository } from '../../src/entity/utils'
describe('Newsletters API', () => {
let user: User
let authToken: string
let newsletterEmails: NewsletterEmail[]
before(async () => {
// create test user and login
@ -25,20 +28,6 @@ describe('Newsletters API', () => {
.send({ fakeEmail: user.email })
authToken = res.body.authToken
// create test newsletter emails
const newsletterEmail1 = await createTestNewsletterEmail(
user,
'Test_email_address_1@omnivore.app'
)
const newsletterEmail2 = await createTestNewsletterEmail(
user,
'Test_email_address_2@omnivore.app'
)
newsletterEmails = [newsletterEmail1, newsletterEmail2]
// create testing subscriptions
await createTestSubscription(user, 'sub', newsletterEmail2)
})
after(async () => {
@ -67,33 +56,94 @@ describe('Newsletters API', () => {
}
`
it('responds with newsletter emails sort by created_at desc', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
expect(
response.body.data.newsletterEmails.newsletterEmails.map((e: any) => {
return {
...e,
createdAt: new Date(e.createdAt).toISOString().split('.')[0] + 'Z',
}
})
).to.eqls([
{
id: newsletterEmails[1].id,
address: newsletterEmails[1].address,
confirmationCode: newsletterEmails[1].confirmationCode,
createdAt:
newsletterEmails[1].createdAt.toISOString().split('.')[0] + 'Z',
subscriptionCount: 1,
},
{
id: newsletterEmails[0].id,
address: newsletterEmails[0].address,
confirmationCode: newsletterEmails[0].confirmationCode,
createdAt:
newsletterEmails[0].createdAt.toISOString().split('.')[0] + 'Z',
subscriptionCount: 0,
},
])
context('when has active subscriptions', () => {
let newsletterEmails: NewsletterEmail[]
before(async () => {
// create test newsletter emails
const newsletterEmail1 = await createTestNewsletterEmail(
user,
'Test_email_address_1@omnivore.app'
)
const newsletterEmail2 = await createTestNewsletterEmail(
user,
'Test_email_address_2@omnivore.app'
)
newsletterEmails = [newsletterEmail1, newsletterEmail2]
// create testing subscriptions
await createTestSubscription(user, 'sub', newsletterEmail2)
})
after(async () => {
// clean up
await getRepository(NewsletterEmail).delete(
newsletterEmails.map((e) => e.id)
)
})
it('responds with newsletter emails sort by created_at desc', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
expect(
response.body.data.newsletterEmails.newsletterEmails.map((e: any) => {
return {
...e,
createdAt:
new Date(e.createdAt).toISOString().split('.')[0] + 'Z',
}
})
).to.eqls([
{
id: newsletterEmails[1].id,
address: newsletterEmails[1].address,
confirmationCode: newsletterEmails[1].confirmationCode,
createdAt:
newsletterEmails[1].createdAt.toISOString().split('.')[0] + 'Z',
subscriptionCount: 1,
},
{
id: newsletterEmails[0].id,
address: newsletterEmails[0].address,
confirmationCode: newsletterEmails[0].confirmationCode,
createdAt:
newsletterEmails[0].createdAt.toISOString().split('.')[0] + 'Z',
subscriptionCount: 0,
},
])
})
})
context('when unsubscribe newsletter email', () => {
let newsletterEmail: NewsletterEmail
before(async () => {
// create test newsletter emails
newsletterEmail = await createTestNewsletterEmail(
user,
'Test_email_address_1@omnivore.app'
)
// create unsubscribed subscriptions
await createTestSubscription(
user,
'sub',
newsletterEmail,
SubscriptionStatus.Unsubscribed
)
})
after(async () => {
// clean up
await getRepository(NewsletterEmail).delete(newsletterEmail.id)
})
it('responds with right count of subscriptions', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
expect(
response.body.data.newsletterEmails.newsletterEmails[0]
.subscriptionCount
).to.eqls(0)
})
})
it('responds status code 400 when invalid query', async () => {
@ -175,8 +225,18 @@ describe('Newsletters API', () => {
})
context('when newsletter email exists', () => {
before(() => {
newsletterEmailId = newsletterEmails[0].id
before(async () => {
// create test newsletter emails
const newsletterEmail = await createTestNewsletterEmail(
user,
'Test_email_address_1@omnivore.app'
)
newsletterEmailId = newsletterEmail.id
})
after(async () => {
// clean up
await getRepository(NewsletterEmail).delete(newsletterEmailId)
})
it('responds with status code 200', async () => {