mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
update api to accommodate rss feed subscriptions
This commit is contained in:
parent
7075375e2b
commit
574636451d
9 changed files with 173 additions and 83 deletions
|
|
@ -83,6 +83,7 @@
|
|||
"pg": "^8.3.3",
|
||||
"postgrator": "^4.2.0",
|
||||
"private-ip": "^2.3.3",
|
||||
"rss-parser": "^3.13.0",
|
||||
"sanitize-html": "^2.3.2",
|
||||
"search-query-parser": "^1.6.0",
|
||||
"snake-case": "^3.0.3",
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ export class Subscription {
|
|||
})
|
||||
status!: SubscriptionStatus
|
||||
|
||||
@ManyToOne(() => NewsletterEmail)
|
||||
@ManyToOne(() => NewsletterEmail, { nullable: true })
|
||||
@JoinColumn({ name: 'newsletter_email_id' })
|
||||
newsletterEmail!: NewsletterEmail
|
||||
newsletterEmail?: NewsletterEmail | null
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
description?: string
|
||||
|
|
|
|||
|
|
@ -1574,12 +1574,13 @@ export type MutationSetWebhookArgs = {
|
|||
|
||||
|
||||
export type MutationSubscribeArgs = {
|
||||
name: Scalars['String'];
|
||||
input: SubscribeInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationUnsubscribeArgs = {
|
||||
name: Scalars['String'];
|
||||
subscriptionId?: InputMaybe<Scalars['ID']>;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1869,6 +1870,7 @@ export type QuerySharedArticleArgs = {
|
|||
|
||||
export type QuerySubscriptionsArgs = {
|
||||
sort?: InputMaybe<SortParams>;
|
||||
type?: InputMaybe<SubscriptionType>;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -2697,6 +2699,12 @@ export enum SubscribeErrorCode {
|
|||
Unauthorized = 'UNAUTHORIZED'
|
||||
}
|
||||
|
||||
export type SubscribeInput = {
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
subscriptionType?: InputMaybe<SubscriptionType>;
|
||||
url?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type SubscribeResult = SubscribeError | SubscribeSuccess;
|
||||
|
||||
export type SubscribeSuccess = {
|
||||
|
|
@ -3695,6 +3703,7 @@ export type ResolversTypes = {
|
|||
String: ResolverTypeWrapper<Scalars['String']>;
|
||||
SubscribeError: ResolverTypeWrapper<SubscribeError>;
|
||||
SubscribeErrorCode: SubscribeErrorCode;
|
||||
SubscribeInput: SubscribeInput;
|
||||
SubscribeResult: ResolversTypes['SubscribeError'] | ResolversTypes['SubscribeSuccess'];
|
||||
SubscribeSuccess: ResolverTypeWrapper<SubscribeSuccess>;
|
||||
Subscription: ResolverTypeWrapper<{}>;
|
||||
|
|
@ -4102,6 +4111,7 @@ export type ResolversParentTypes = {
|
|||
SortParams: SortParams;
|
||||
String: Scalars['String'];
|
||||
SubscribeError: SubscribeError;
|
||||
SubscribeInput: SubscribeInput;
|
||||
SubscribeResult: ResolversParentTypes['SubscribeError'] | ResolversParentTypes['SubscribeSuccess'];
|
||||
SubscribeSuccess: SubscribeSuccess;
|
||||
Subscription: {};
|
||||
|
|
@ -5123,7 +5133,7 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
|
|||
setShareHighlight?: Resolver<ResolversTypes['SetShareHighlightResult'], ParentType, ContextType, RequireFields<MutationSetShareHighlightArgs, 'input'>>;
|
||||
setUserPersonalization?: Resolver<ResolversTypes['SetUserPersonalizationResult'], ParentType, ContextType, RequireFields<MutationSetUserPersonalizationArgs, 'input'>>;
|
||||
setWebhook?: Resolver<ResolversTypes['SetWebhookResult'], ParentType, ContextType, RequireFields<MutationSetWebhookArgs, 'input'>>;
|
||||
subscribe?: Resolver<ResolversTypes['SubscribeResult'], ParentType, ContextType, RequireFields<MutationSubscribeArgs, 'name'>>;
|
||||
subscribe?: Resolver<ResolversTypes['SubscribeResult'], ParentType, ContextType, RequireFields<MutationSubscribeArgs, 'input'>>;
|
||||
unsubscribe?: Resolver<ResolversTypes['UnsubscribeResult'], ParentType, ContextType, RequireFields<MutationUnsubscribeArgs, 'name'>>;
|
||||
updateHighlight?: Resolver<ResolversTypes['UpdateHighlightResult'], ParentType, ContextType, RequireFields<MutationUpdateHighlightArgs, 'input'>>;
|
||||
updateHighlightReply?: Resolver<ResolversTypes['UpdateHighlightReplyResult'], ParentType, ContextType, RequireFields<MutationUpdateHighlightReplyArgs, 'input'>>;
|
||||
|
|
|
|||
|
|
@ -1151,8 +1151,8 @@ type Mutation {
|
|||
setShareHighlight(input: SetShareHighlightInput!): SetShareHighlightResult!
|
||||
setUserPersonalization(input: SetUserPersonalizationInput!): SetUserPersonalizationResult!
|
||||
setWebhook(input: SetWebhookInput!): SetWebhookResult!
|
||||
subscribe(name: String!): SubscribeResult!
|
||||
unsubscribe(name: String!): UnsubscribeResult!
|
||||
subscribe(input: SubscribeInput!): SubscribeResult!
|
||||
unsubscribe(name: String!, subscriptionId: ID): UnsubscribeResult!
|
||||
updateHighlight(input: UpdateHighlightInput!): UpdateHighlightResult!
|
||||
updateHighlightReply(input: UpdateHighlightReplyInput!): UpdateHighlightReplyResult!
|
||||
updateLabel(input: UpdateLabelInput!): UpdateLabelResult!
|
||||
|
|
@ -1308,7 +1308,7 @@ type Query {
|
|||
search(after: String, first: Int, format: String, includeContent: Boolean, query: String): SearchResult!
|
||||
sendInstallInstructions: SendInstallInstructionsResult!
|
||||
sharedArticle(selectedHighlightId: String, slug: String!, username: String!): SharedArticleResult!
|
||||
subscriptions(sort: SortParams): SubscriptionsResult!
|
||||
subscriptions(sort: SortParams, type: SubscriptionType): SubscriptionsResult!
|
||||
typeaheadSearch(first: Int, query: String!): TypeaheadSearchResult!
|
||||
updatesSince(after: String, first: Int, since: Date!, sort: SortParams): UpdatesSinceResult!
|
||||
user(userId: ID, username: String): UserResult!
|
||||
|
|
@ -2051,6 +2051,12 @@ enum SubscribeErrorCode {
|
|||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
input SubscribeInput {
|
||||
name: String
|
||||
subscriptionType: SubscriptionType
|
||||
url: String
|
||||
}
|
||||
|
||||
union SubscribeResult = SubscribeError | SubscribeSuccess
|
||||
|
||||
type SubscribeSuccess {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ILike } from 'typeorm'
|
||||
import Parser from 'rss-parser'
|
||||
import { Subscription } from '../../entity/subscription'
|
||||
import { User } from '../../entity/user'
|
||||
import { getRepository } from '../../entity/utils'
|
||||
|
|
@ -16,6 +16,7 @@ import {
|
|||
SubscriptionsErrorCode,
|
||||
SubscriptionsSuccess,
|
||||
SubscriptionStatus,
|
||||
SubscriptionType,
|
||||
UnsubscribeError,
|
||||
UnsubscribeErrorCode,
|
||||
UnsubscribeSuccess,
|
||||
|
|
@ -25,11 +26,13 @@ import { analytics } from '../../utils/analytics'
|
|||
import { authorized } from '../../utils/helpers'
|
||||
import { createImageProxyUrl } from '../../utils/imageproxy'
|
||||
|
||||
const parser = new Parser()
|
||||
|
||||
export const subscriptionsResolver = authorized<
|
||||
SubscriptionsSuccess,
|
||||
SubscriptionsError,
|
||||
QuerySubscriptionsArgs
|
||||
>(async (_obj, { sort }, { claims: { uid }, log }) => {
|
||||
>(async (_obj, { sort, type: subscriptionType }, { claims: { uid }, log }) => {
|
||||
log.info('subscriptionsResolver')
|
||||
|
||||
analytics.track({
|
||||
|
|
@ -41,7 +44,8 @@ export const subscriptionsResolver = authorized<
|
|||
})
|
||||
|
||||
try {
|
||||
const sortBy = sort?.by === SortBy.UpdatedTime ? 'updatedAt' : 'createdAt'
|
||||
const sortBy =
|
||||
sort?.by === SortBy.UpdatedTime ? 'lastFetchedAt' : 'createdAt'
|
||||
const sortOrder = sort?.order === SortOrder.Ascending ? 'ASC' : 'DESC'
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
|
|
@ -52,10 +56,11 @@ export const subscriptionsResolver = authorized<
|
|||
|
||||
const subscriptions = await getRepository(Subscription)
|
||||
.createQueryBuilder('subscription')
|
||||
.innerJoinAndSelect('subscription.newsletterEmail', 'newsletterEmail')
|
||||
.leftJoinAndSelect('subscription.newsletterEmail', 'newsletterEmail')
|
||||
.where({
|
||||
user: { id: uid },
|
||||
status: SubscriptionStatus.Active,
|
||||
type: subscriptionType || SubscriptionType.Newsletter, // default to newsletter
|
||||
})
|
||||
.orderBy('subscription.' + sortBy, sortOrder)
|
||||
.getMany()
|
||||
|
|
@ -64,7 +69,7 @@ export const subscriptionsResolver = authorized<
|
|||
subscriptions: subscriptions.map((s) => ({
|
||||
...s,
|
||||
icon: s.icon && createImageProxyUrl(s.icon, 128, 128),
|
||||
newsletterEmail: s.newsletterEmail.address,
|
||||
newsletterEmail: s.newsletterEmail?.address,
|
||||
})),
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -79,7 +84,7 @@ export const unsubscribeResolver = authorized<
|
|||
UnsubscribeSuccess,
|
||||
UnsubscribeError,
|
||||
MutationUnsubscribeArgs
|
||||
>(async (_, { name }, { claims: { uid }, log }) => {
|
||||
>(async (_, { name, subscriptionId }, { claims: { uid }, log }) => {
|
||||
log.info('unsubscribeResolver')
|
||||
|
||||
try {
|
||||
|
|
@ -90,13 +95,20 @@ export const unsubscribeResolver = authorized<
|
|||
}
|
||||
}
|
||||
|
||||
const subscription = await getRepository(Subscription)
|
||||
const queryBuilder = getRepository(Subscription)
|
||||
.createQueryBuilder('subscription')
|
||||
.innerJoinAndSelect('subscription.newsletterEmail', 'newsletterEmail')
|
||||
.leftJoinAndSelect('subscription.newsletterEmail', 'newsletterEmail')
|
||||
.where({ user: { id: uid } })
|
||||
.andWhere('LOWER(name) = LOWER(:name)', { name }) // case insensitive
|
||||
.getOne()
|
||||
|
||||
if (subscriptionId) {
|
||||
// if subscriptionId is provided, ignore name
|
||||
queryBuilder.andWhere({ id: subscriptionId })
|
||||
} else {
|
||||
// if subscriptionId is not provided, use name for old clients
|
||||
queryBuilder.andWhere({ name })
|
||||
}
|
||||
|
||||
const subscription = await queryBuilder.getOne()
|
||||
if (!subscription) {
|
||||
return {
|
||||
errorCodes: [UnsubscribeErrorCode.NotFound],
|
||||
|
|
@ -128,7 +140,7 @@ export const unsubscribeResolver = authorized<
|
|||
return {
|
||||
subscription: {
|
||||
...subscription,
|
||||
newsletterEmail: subscription.newsletterEmail.address,
|
||||
newsletterEmail: subscription.newsletterEmail?.address,
|
||||
},
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -143,7 +155,7 @@ export const subscribeResolver = authorized<
|
|||
SubscribeSuccess,
|
||||
SubscribeError,
|
||||
MutationSubscribeArgs
|
||||
>(async (_, { name }, { claims: { uid }, log }) => {
|
||||
>(async (_, { input }, { claims: { uid }, log }) => {
|
||||
log.info('subscribeResolver')
|
||||
|
||||
try {
|
||||
|
|
@ -154,10 +166,13 @@ export const subscribeResolver = authorized<
|
|||
}
|
||||
}
|
||||
|
||||
// find existing subscription
|
||||
const subscription = await getRepository(Subscription).findOneBy({
|
||||
name: ILike(name),
|
||||
url: input.url || undefined,
|
||||
name: input.name || undefined,
|
||||
user: { id: uid },
|
||||
status: SubscriptionStatus.Active,
|
||||
type: input.subscriptionType || SubscriptionType.Rss, // default to rss
|
||||
})
|
||||
if (subscription) {
|
||||
return {
|
||||
|
|
@ -165,34 +180,69 @@ export const subscribeResolver = authorized<
|
|||
}
|
||||
}
|
||||
|
||||
const subscribeHandler = getSubscribeHandler(name)
|
||||
if (!subscribeHandler) {
|
||||
return {
|
||||
errorCodes: [SubscribeErrorCode.NotFound],
|
||||
}
|
||||
}
|
||||
|
||||
const newSubscriptions = await subscribeHandler.handleSubscribe(uid, name)
|
||||
if (!newSubscriptions) {
|
||||
return {
|
||||
errorCodes: [SubscribeErrorCode.BadRequest],
|
||||
}
|
||||
}
|
||||
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
event: 'subscribed',
|
||||
properties: {
|
||||
name,
|
||||
...input,
|
||||
env: env.server.apiEnv,
|
||||
},
|
||||
})
|
||||
|
||||
// create new newsletter subscription
|
||||
if (input.name && input.subscriptionType === SubscriptionType.Newsletter) {
|
||||
const subscribeHandler = getSubscribeHandler(input.name)
|
||||
if (!subscribeHandler) {
|
||||
return {
|
||||
errorCodes: [SubscribeErrorCode.NotFound],
|
||||
}
|
||||
}
|
||||
|
||||
const newSubscriptions = await subscribeHandler.handleSubscribe(
|
||||
uid,
|
||||
input.name
|
||||
)
|
||||
if (!newSubscriptions) {
|
||||
return {
|
||||
errorCodes: [SubscribeErrorCode.BadRequest],
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
subscriptions: newSubscriptions.map((s) => ({
|
||||
...s,
|
||||
newsletterEmail: s.newsletterEmail?.address,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
// create new rss subscription
|
||||
if (input.url) {
|
||||
// validate rss feed
|
||||
const feed = await parser.parseURL(input.url)
|
||||
|
||||
const newSubscription = await getRepository(Subscription).save({
|
||||
name: feed.title,
|
||||
url: input.url,
|
||||
user: { id: uid },
|
||||
type: SubscriptionType.Rss,
|
||||
description: feed.description,
|
||||
icon: feed.image?.url,
|
||||
})
|
||||
|
||||
return {
|
||||
subscriptions: [
|
||||
{
|
||||
...newSubscription,
|
||||
newsletterEmail: null,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
log.info('missing url or name')
|
||||
return {
|
||||
subscriptions: newSubscriptions.map((s) => ({
|
||||
...s,
|
||||
newsletterEmail: s.newsletterEmail.address,
|
||||
})),
|
||||
errorCodes: [SubscribeErrorCode.BadRequest],
|
||||
}
|
||||
} catch (error) {
|
||||
log.error('failed to subscribe', error)
|
||||
|
|
|
|||
|
|
@ -2486,6 +2486,12 @@ const schema = gql`
|
|||
ALREADY_EXISTS
|
||||
}
|
||||
|
||||
input SubscribeInput {
|
||||
url: String
|
||||
name: String
|
||||
subscriptionType: SubscriptionType
|
||||
}
|
||||
|
||||
# Mutations
|
||||
type Mutation {
|
||||
googleLogin(input: GoogleLoginInput!): LoginResult!
|
||||
|
|
@ -2547,8 +2553,8 @@ const schema = gql`
|
|||
deleteLabel(id: ID!): DeleteLabelResult!
|
||||
setLabels(input: SetLabelsInput!): SetLabelsResult!
|
||||
generateApiKey(input: GenerateApiKeyInput!): GenerateApiKeyResult!
|
||||
unsubscribe(name: String!): UnsubscribeResult!
|
||||
subscribe(name: String!): SubscribeResult!
|
||||
unsubscribe(name: String!, subscriptionId: ID): UnsubscribeResult!
|
||||
subscribe(input: SubscribeInput!): SubscribeResult!
|
||||
addPopularRead(name: String!): AddPopularReadResult!
|
||||
setWebhook(input: SetWebhookInput!): SetWebhookResult!
|
||||
deleteWebhook(id: ID!): DeleteWebhookResult!
|
||||
|
|
@ -2628,7 +2634,10 @@ const schema = gql`
|
|||
includeContent: Boolean
|
||||
format: String
|
||||
): SearchResult!
|
||||
subscriptions(sort: SortParams): SubscriptionsResult!
|
||||
subscriptions(
|
||||
sort: SortParams
|
||||
type: SubscriptionType
|
||||
): SubscriptionsResult!
|
||||
sendInstallInstructions: SendInstallInstructionsResult!
|
||||
webhooks: WebhooksResult!
|
||||
webhook(id: ID!): WebhookResult!
|
||||
|
|
|
|||
|
|
@ -131,26 +131,30 @@ export const saveSubscription = async ({
|
|||
}
|
||||
|
||||
export const unsubscribe = async (subscription: Subscription) => {
|
||||
let unsubscribed = false
|
||||
if (subscription.unsubscribeMailTo) {
|
||||
// unsubscribe by sending email
|
||||
unsubscribed = await sendUnsubscribeEmail(
|
||||
subscription.unsubscribeMailTo,
|
||||
subscription.newsletterEmail.address
|
||||
)
|
||||
}
|
||||
// TODO: find a good way to unsubscribe by url if email fails or not provided
|
||||
// because it often requires clicking a button on the page to unsubscribe
|
||||
// unsubscribe from newsletter
|
||||
if (subscription.type === SubscriptionType.Newsletter) {
|
||||
let unsubscribed = false
|
||||
|
||||
if (!unsubscribed) {
|
||||
// update subscription status to unsubscribed if failed to unsubscribe
|
||||
console.log('Failed to unsubscribe', subscription.id)
|
||||
return getRepository(Subscription).update(subscription.id, {
|
||||
status: SubscriptionStatus.Unsubscribed,
|
||||
})
|
||||
if (subscription.unsubscribeMailTo && subscription.newsletterEmail) {
|
||||
// unsubscribe by sending email
|
||||
unsubscribed = await sendUnsubscribeEmail(
|
||||
subscription.unsubscribeMailTo,
|
||||
subscription.newsletterEmail.address
|
||||
)
|
||||
}
|
||||
// TODO: find a good way to unsubscribe by url if email fails or not provided
|
||||
// because it often requires clicking a button on the page to unsubscribe
|
||||
|
||||
if (!unsubscribed) {
|
||||
// update subscription status to unsubscribed if failed to unsubscribe
|
||||
console.log('Failed to unsubscribe', subscription.id)
|
||||
return getRepository(Subscription).update(subscription.id, {
|
||||
status: SubscriptionStatus.Unsubscribed,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// delete the subscription if successfully unsubscribed
|
||||
// delete the subscription if successfully unsubscribed or it's an rss feed
|
||||
await getRepository(Subscription).delete(subscription.id)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
import Postgrator from 'postgrator'
|
||||
import { User } from '../src/entity/user'
|
||||
import { Profile } from '../src/entity/profile'
|
||||
import { Page } from '../src/entity/page'
|
||||
import { Link } from '../src/entity/link'
|
||||
import { Reminder } from '../src/entity/reminder'
|
||||
import { NewsletterEmail } from '../src/entity/newsletter_email'
|
||||
import { UserDeviceToken } from '../src/entity/user_device_tokens'
|
||||
import { Label } from '../src/entity/label'
|
||||
import { Subscription } from '../src/entity/subscription'
|
||||
import { AppDataSource } from '../src/server'
|
||||
import { getRepository, setClaims } from '../src/entity/utils'
|
||||
import { createUser } from '../src/services/create_user'
|
||||
import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
|
||||
import { SubscriptionStatus } from '../src/generated/graphql'
|
||||
import { Integration } from '../src/entity/integration'
|
||||
import { FindOptionsWhere } from 'typeorm'
|
||||
import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
|
||||
import { Integration } from '../src/entity/integration'
|
||||
import { Label } from '../src/entity/label'
|
||||
import { Link } from '../src/entity/link'
|
||||
import { NewsletterEmail } from '../src/entity/newsletter_email'
|
||||
import { Page } from '../src/entity/page'
|
||||
import { Profile } from '../src/entity/profile'
|
||||
import { Reminder } from '../src/entity/reminder'
|
||||
import { Subscription } from '../src/entity/subscription'
|
||||
import { User } from '../src/entity/user'
|
||||
import { UserDeviceToken } from '../src/entity/user_device_tokens'
|
||||
import { getRepository, setClaims } from '../src/entity/utils'
|
||||
import { SubscriptionStatus, SubscriptionType } from '../src/generated/graphql'
|
||||
import { AppDataSource } from '../src/server'
|
||||
import { createUser } from '../src/services/create_user'
|
||||
|
||||
const runMigrations = async () => {
|
||||
const migrationDirectory = __dirname + '/../../db/migrations'
|
||||
|
|
@ -199,7 +199,8 @@ export const createTestSubscription = async (
|
|||
name: string,
|
||||
newsletterEmail?: NewsletterEmail,
|
||||
status = SubscriptionStatus.Active,
|
||||
unsubscribeMailTo?: string
|
||||
unsubscribeMailTo?: string,
|
||||
subscriptionType = SubscriptionType.Newsletter
|
||||
): Promise<Subscription> => {
|
||||
return getRepository(Subscription).save({
|
||||
user,
|
||||
|
|
@ -207,6 +208,8 @@ export const createTestSubscription = async (
|
|||
newsletterEmail,
|
||||
status,
|
||||
unsubscribeMailTo,
|
||||
lastFetchedAt: new Date(),
|
||||
type: subscriptionType,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ import { NewsletterEmail } from '../../src/entity/newsletter_email'
|
|||
import { Subscription } from '../../src/entity/subscription'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { getRepository } from '../../src/entity/utils'
|
||||
import { SubscriptionStatus } from '../../src/generated/graphql'
|
||||
import {
|
||||
SubscriptionStatus,
|
||||
SubscriptionType,
|
||||
} from '../../src/generated/graphql'
|
||||
import { UNSUBSCRIBE_EMAIL_TEXT } from '../../src/services/subscriptions'
|
||||
import * as sendEmail from '../../src/utils/sendEmail'
|
||||
import { createTestSubscription, createTestUser, deleteTestUser } from '../db'
|
||||
|
|
@ -35,7 +38,7 @@ describe('Subscriptions API', () => {
|
|||
confirmationCode: 'test',
|
||||
})
|
||||
|
||||
// create testing subscriptions
|
||||
// create testing newsletter subscriptions
|
||||
const sub1 = await createTestSubscription(user, 'sub_1', newsletterEmail)
|
||||
const sub2 = await createTestSubscription(user, 'sub_2', newsletterEmail)
|
||||
// create a unsubscribed subscription
|
||||
|
|
@ -45,8 +48,15 @@ describe('Subscriptions API', () => {
|
|||
newsletterEmail,
|
||||
SubscriptionStatus.Unsubscribed
|
||||
)
|
||||
// create a subscription without a newsletter email
|
||||
await createTestSubscription(user, 'sub_4')
|
||||
// create an rss feed subscription
|
||||
await createTestSubscription(
|
||||
user,
|
||||
'sub_4',
|
||||
undefined,
|
||||
SubscriptionStatus.Active,
|
||||
undefined,
|
||||
SubscriptionType.Rss
|
||||
)
|
||||
subscriptions = [sub2, sub1]
|
||||
})
|
||||
|
||||
|
|
@ -143,10 +153,7 @@ describe('Subscriptions API', () => {
|
|||
sinon.fake.resolves(true)
|
||||
)
|
||||
|
||||
const res = await graphqlRequest(
|
||||
query(name.toUpperCase()),
|
||||
authToken
|
||||
).expect(200)
|
||||
const res = await graphqlRequest(query(name), authToken).expect(200)
|
||||
|
||||
expect(res.body.data.unsubscribe.subscription).to.eql({
|
||||
id: subscription.id,
|
||||
|
|
|
|||
Loading…
Reference in a new issue