fix some rls issue

This commit is contained in:
Hongbo Wu 2023-09-07 12:35:05 +08:00
parent cea5f790d8
commit 669cddeec8
55 changed files with 689 additions and 627 deletions

View file

@ -14,6 +14,7 @@ import {
RevokeApiKeySuccess,
} from '../../generated/graphql'
import { getRepository } from '../../repository'
import { findApiKeys } from '../../services/api_key'
import { analytics } from '../../utils/analytics'
import { generateApiKey, hashApiKey } from '../../utils/auth'
import { authorized } from '../../utils/helpers'
@ -21,14 +22,7 @@ import { authorized } from '../../utils/helpers'
export const apiKeysResolver = authorized<ApiKeysSuccess, ApiKeysError>(
async (_, __, { log, uid }) => {
try {
const apiKeys = await getRepository(ApiKey).find({
select: ['id', 'name', 'scopes', 'expiresAt', 'createdAt', 'usedAt'],
where: { user: { id: uid } },
order: {
usedAt: { direction: 'DESC', nulls: 'last' },
createdAt: 'DESC',
},
})
const apiKeys = await findApiKeys(uid)
return {
apiKeys,

View file

@ -1,5 +1,5 @@
import { DeepPartial } from 'typeorm'
import { Integration, IntegrationType } from '../../entity/integration'
import { User } from '../../entity/user'
import { env } from '../../env'
import {
DeleteIntegrationError,
@ -18,8 +18,14 @@ import {
SetIntegrationErrorCode,
SetIntegrationSuccess,
} from '../../generated/graphql'
import { getRepository } from '../../repository'
import { getIntegrationService } from '../../services/integrations'
import {
createIntegration,
findIntegration,
findIntegrations,
getIntegrationService,
removeIntegration,
updateIntegration,
} from '../../services/integrations'
import { analytics } from '../../utils/analytics'
import {
deleteTask,
@ -32,29 +38,17 @@ export const setIntegrationResolver = authorized<
SetIntegrationSuccess,
SetIntegrationError,
MutationSetIntegrationArgs
>(async (_, { input }, { claims: { uid }, log }) => {
log.info('setIntegrationResolver')
>(async (_, { input }, { uid, log }) => {
try {
const user = await getRepository(User).findOneBy({ id: uid })
if (!user) {
return {
errorCodes: [SetIntegrationErrorCode.Unauthorized],
}
}
const integrationToSave: Partial<Integration> = {
const integrationToSave: DeepPartial<Integration> = {
...input,
user,
user: { id: uid },
id: input.id || undefined,
type: input.type || IntegrationType.Export,
}
if (input.id) {
// Update
const existingIntegration = await getRepository(Integration).findOne({
where: { id: input.id },
relations: ['user'],
})
const existingIntegration = await findIntegration({ id: input.id }, uid)
if (!existingIntegration) {
return {
errorCodes: [SetIntegrationErrorCode.NotFound],
@ -82,18 +76,18 @@ export const setIntegrationResolver = authorized<
}
// save integration
const integration = await getRepository(Integration).save(integrationToSave)
const integration = await createIntegration(integrationToSave, uid)
if (
integrationToSave.type === IntegrationType.Export &&
(!integrationToSave.id || integrationToSave.enabled)
) {
// create a task to sync all the pages if new integration or enable integration (export type)
const taskName = await enqueueSyncWithIntegration(user.id, input.name)
const taskName = await enqueueSyncWithIntegration(uid, input.name)
log.info('enqueued task', taskName)
// update task name in integration
await getRepository(Integration).update(integration.id, { taskName })
await updateIntegration(integration.id, { taskName }, uid)
integration.taskName = taskName
} else if (integrationToSave.taskName) {
// delete the task if disable integration and task exists
@ -101,9 +95,13 @@ export const setIntegrationResolver = authorized<
log.info('task deleted', integrationToSave.taskName)
// update task name in integration
await getRepository(Integration).update(integration.id, {
taskName: null,
})
await updateIntegration(
integration.id,
{
taskName: null,
},
uid
)
integration.taskName = null
}
@ -131,19 +129,9 @@ export const setIntegrationResolver = authorized<
export const integrationsResolver = authorized<
IntegrationsSuccess,
IntegrationsError
>(async (_, __, { claims: { uid }, log }) => {
log.info('integrationsResolver')
>(async (_, __, { uid, log }) => {
try {
const user = await getRepository(User).findOneBy({ id: uid })
if (!user) {
return {
errorCodes: [IntegrationsErrorCode.Unauthorized],
}
}
const integrations = await getRepository(Integration).findBy({
user: { id: uid },
})
const integrations = await findIntegrations(uid)
return {
integrations,
@ -165,17 +153,7 @@ export const deleteIntegrationResolver = authorized<
log.info('deleteIntegrationResolver')
try {
const user = await getRepository(User).findOneBy({ id: uid })
if (!user) {
return {
errorCodes: [DeleteIntegrationErrorCode.Unauthorized],
}
}
const integration = await getRepository(Integration).findOne({
where: { id },
relations: ['user'],
})
const integration = await findIntegration({ id }, uid)
if (!integration) {
return {
@ -183,21 +161,13 @@ export const deleteIntegrationResolver = authorized<
}
}
if (integration.user.id !== uid) {
return {
errorCodes: [DeleteIntegrationErrorCode.Unauthorized],
}
}
if (integration.taskName) {
// delete the task if task exists
await deleteTask(integration.taskName)
log.info('task deleted', integration.taskName)
}
const deletedIntegration = await getRepository(Integration).remove(
integration
)
const deletedIntegration = await removeIntegration(integration, uid)
deletedIntegration.id = id
analytics.track({
@ -229,10 +199,7 @@ export const importFromIntegrationResolver = authorized<
log.info('importFromIntegrationResolver')
try {
const integration = await getRepository(Integration).findOne({
where: { id: integrationId, user: { id: uid } },
relations: ['user'],
})
const integration = await findIntegration({ id: integrationId }, uid)
if (!integration) {
return {
@ -251,7 +218,7 @@ export const importFromIntegrationResolver = authorized<
authToken
)
// update task name in integration
await getRepository(Integration).update(integration.id, { taskName })
await updateIntegration(integration.id, { taskName }, uid)
analytics.track({
userId: uid,

View file

@ -15,9 +15,9 @@ import {
import {
createDeviceToken,
deleteDeviceToken,
getDeviceToken,
getDeviceTokenByToken,
getDeviceTokensByUserId,
findDeviceTokenById,
findDeviceTokenByToken,
findDeviceTokensByUserId,
} from '../../services/user_device_tokens'
import { analytics } from '../../utils/analytics'
import { authorized } from '../../utils/helpers'
@ -44,7 +44,7 @@ export const setDeviceTokenResolver = authorized<
try {
// when token is null, we are deleting it
if (!token && id) {
const deviceToken = await getDeviceToken(id)
const deviceToken = await findDeviceTokenById(id)
if (!deviceToken) {
log.error('device token not found', id)
@ -107,7 +107,7 @@ export const setDeviceTokenResolver = authorized<
token
) {
// duplicate token
const deviceToken = await getDeviceTokenByToken(token)
const deviceToken = await findDeviceTokenByToken(token)
if (!deviceToken) {
return {
@ -139,7 +139,7 @@ export const deviceTokensResolver = authorized<
},
})
const deviceTokens = await getDeviceTokensByUserId(uid)
const deviceTokens = await findDeviceTokensByUserId(uid)
log.info('deviceTokens', deviceTokens)
return {

View file

@ -3,7 +3,7 @@ import express from 'express'
import * as jwt from 'jsonwebtoken'
import { env } from '../env'
import { Claims } from '../resolvers/types'
import { getDeviceTokensByUserId } from '../services/user_device_tokens'
import { findDeviceTokensByUserId } from '../services/user_device_tokens'
import { corsConfig } from '../utils/corsConfig'
import {
PushNotificationType,
@ -42,7 +42,7 @@ export function notificationRouter() {
return res.status(400).send({ errorCode: 'BAD_DATA' })
}
const tokens = await getDeviceTokensByUserId(userId)
const tokens = await findDeviceTokensByUserId(userId)
if (tokens.length === 0) {
return res.status(400).send({ errorCode: 'NO_DEVICE_TOKENS' })
}

View file

@ -10,7 +10,7 @@ import { env } from '../../env'
import { UploadFileStatus } from '../../generated/graphql'
import { authTrx } from '../../repository'
import { createLibraryItem } from '../../services/library_item'
import { getNewsletterEmail } from '../../services/newsletters'
import { findNewsletterEmail } from '../../services/newsletters'
import { updateReceivedEmail } from '../../services/received_emails'
import {
findUploadFileById,
@ -45,7 +45,7 @@ export function emailAttachmentRouter() {
return res.status(401).send('UNAUTHORIZED')
}
const newsletterEmail = await getNewsletterEmail(email)
const newsletterEmail = await findNewsletterEmail(email)
if (!newsletterEmail || !newsletterEmail.user) {
return res.status(401).send('UNAUTHORIZED')
}
@ -109,7 +109,7 @@ export function emailAttachmentRouter() {
return res.status(401).send('UNAUTHORIZED')
}
const newsletterEmail = await getNewsletterEmail(email)
const newsletterEmail = await findNewsletterEmail(email)
if (!newsletterEmail || !newsletterEmail.user) {
return res.status(401).send('UNAUTHORIZED')
}

View file

@ -2,7 +2,7 @@ import cors from 'cors'
import express from 'express'
import { env } from '../../env'
import { readPushSubscription } from '../../pubsub'
import { getNewsletterEmail } from '../../services/newsletters'
import { findNewsletterEmail } from '../../services/newsletters'
import { saveReceivedEmail } from '../../services/received_emails'
import { saveNewsletter } from '../../services/save_newsletter_email'
import { analytics } from '../../utils/analytics'
@ -62,7 +62,7 @@ export function emailsServiceRouter() {
}
// get user from newsletter email
const newsletterEmail = await getNewsletterEmail(data.to)
const newsletterEmail = await findNewsletterEmail(data.to)
if (!newsletterEmail) {
logger.info('newsletter email not found', { email: data.to })
@ -150,7 +150,7 @@ export function emailsServiceRouter() {
try {
// get user from newsletter email
const newsletterEmail = await getNewsletterEmail(req.body.to)
const newsletterEmail = await findNewsletterEmail(req.body.to)
if (!newsletterEmail) {
logger.info('newsletter email not found', { email: req.body.to })

View file

@ -2,7 +2,7 @@ import express from 'express'
import { SubscriptionStatus } from '../../generated/graphql'
import { createPubSubClient, readPushSubscription } from '../../pubsub'
import {
getNewsletterEmail,
findNewsletterEmail,
updateConfirmationCode,
} from '../../services/newsletters'
import { updateReceivedEmail } from '../../services/received_emails'
@ -105,7 +105,7 @@ export function newsletterServiceRouter() {
}
// get user from newsletter email
const newsletterEmail = await getNewsletterEmail(data.email)
const newsletterEmail = await findNewsletterEmail(data.email)
if (!newsletterEmail) {
logger.info(`newsletter email not found: ${data.email}`)
return res.status(200).send('Not Found')

View file

@ -0,0 +1,41 @@
import { FindOptionsWhere } from 'typeorm'
import { ApiKey } from '../entity/api_key'
import { authTrx } from '../repository'
export const findApiKeys = async (
userId: string,
where?: FindOptionsWhere<ApiKey>[] | FindOptionsWhere<ApiKey>,
select?: (keyof ApiKey)[]
) => {
return authTrx(
(t) =>
t.getRepository(ApiKey).find({
select: select || [
'id',
'name',
'scopes',
'expiresAt',
'createdAt',
'usedAt',
],
where,
order: {
usedAt: { direction: 'DESC', nulls: 'last' },
createdAt: 'DESC',
},
}),
undefined,
userId
)
}
export const deleteApiKey = async (
criteria: string[] | FindOptionsWhere<ApiKey>,
userId: string
) => {
return authTrx(
async (t) => t.getRepository(ApiKey).delete(criteria),
undefined,
userId
)
}

View file

@ -1,5 +1,5 @@
import * as jwt from 'jsonwebtoken'
import { IsNull, Not } from 'typeorm'
import { DeepPartial, FindOptionsWhere, IsNull, Not } from 'typeorm'
import { Feature } from '../entity/feature'
import { env } from '../env'
import { authTrx, entityManager } from '../repository'
@ -110,12 +110,49 @@ export const isOptedIn = async (name: FeatureName): Promise<boolean> => {
return !!feature
}
export const getFeature = async (
name: FeatureName
export const findFeatureByName = async (
name: FeatureName,
userId?: string
): Promise<Feature | null> => {
return authTrx((t) =>
t.getRepository(Feature).findOneBy({
name,
})
return authTrx(
(t) =>
t.getRepository(Feature).findOneBy({
name,
}),
undefined,
userId
)
}
export const deleteFeature = async (
criteria: string[] | FindOptionsWhere<Feature>,
userId: string
) => {
return authTrx(
(t) => t.getRepository(Feature).delete(criteria),
undefined,
userId
)
}
export const createFeature = async (
feature: DeepPartial<Feature>,
userId: string
) => {
return authTrx(
(t) => t.getRepository(Feature).save(feature),
undefined,
userId
)
}
export const createFeatures = async (
features: DeepPartial<Feature>[],
userId: string
) => {
return authTrx(
(t) => t.getRepository(Feature).save(features),
undefined,
userId
)
}

View file

@ -1,6 +1,9 @@
import { ReadwiseIntegration } from './readwise'
import { DeepPartial, FindOptionsWhere } from 'typeorm'
import { Integration } from '../../entity/integration'
import { authTrx } from '../../repository'
import { IntegrationService } from './integration'
import { PocketIntegration } from './pocket'
import { ReadwiseIntegration } from './readwise'
const integrations: IntegrationService[] = [
new ReadwiseIntegration(),
@ -14,3 +17,70 @@ export const getIntegrationService = (name: string): IntegrationService => {
}
return service
}
export const deleteIntegrations = async (
userId: string,
criteria: string[] | FindOptionsWhere<Integration>
) => {
return authTrx(
async (t) => t.getRepository(Integration).delete(criteria),
undefined,
userId
)
}
export const removeIntegration = async (
integration: Integration,
userId: string
) => {
return authTrx(
async (t) => t.getRepository(Integration).remove(integration),
undefined,
userId
)
}
export const findIntegration = async (
where: FindOptionsWhere<Integration> | FindOptionsWhere<Integration>[],
userId: string
) => {
return authTrx(
async (t) => t.getRepository(Integration).findOneBy(where),
undefined,
userId
)
}
export const findIntegrations = async (
userId: string,
where?: FindOptionsWhere<Integration> | FindOptionsWhere<Integration>[]
) => {
return authTrx(
async (t) => t.getRepository(Integration).find({ where }),
undefined,
userId
)
}
export const createIntegration = async (
integration: DeepPartial<Integration>,
userId: string
) => {
return authTrx(
async (t) => t.getRepository(Integration).save(integration),
undefined,
userId
)
}
export const updateIntegration = async (
id: string,
integration: DeepPartial<Integration>,
userId: string
) => {
return authTrx(
async (t) => t.getRepository(Integration).update(id, integration),
undefined,
userId
)
}

View file

@ -1,4 +1,4 @@
import { In } from 'typeorm'
import { FindOptionsWhere, In } from 'typeorm'
import { EntityLabel } from '../entity/entity_label'
import { Label } from '../entity/label'
import { createPubSubClient, EntityType } from '../pubsub'
@ -148,3 +148,27 @@ export const findLabelsByIds = async (ids: string[]): Promise<Label[]> => {
})
})
}
export const createLabel = async (
name: string,
color: string,
userId: string
): Promise<Label> => {
return authTrx(
(t) =>
t.withRepository(labelRepository).createLabel({ name, color }, userId),
undefined,
userId
)
}
export const deleteLabels = async (
criteria: string[] | FindOptionsWhere<Label>,
userId: string
) => {
return authTrx(
async (t) => t.withRepository(labelRepository).delete(criteria),
undefined,
userId
)
}

View file

@ -355,15 +355,19 @@ export const updateLibraryItem = async (
userId: string,
pubsub = createPubSubClient()
): Promise<LibraryItem> => {
const updatedLibraryItem = await authTrx(async (tx) => {
const itemRepo = tx.withRepository(libraryItemRepository)
await itemRepo.update(
id,
libraryItem as QueryDeepPartialEntity<LibraryItem>
)
const updatedLibraryItem = await authTrx(
async (tx) => {
const itemRepo = tx.withRepository(libraryItemRepository)
await itemRepo.update(
id,
libraryItem as QueryDeepPartialEntity<LibraryItem>
)
return itemRepo.findOneByOrFail({ id })
})
return itemRepo.findOneByOrFail({ id })
},
undefined,
userId
)
await pubsub.entityUpdated<DeepPartial<LibraryItem>>(
EntityType.PAGE,

View file

@ -18,7 +18,8 @@ const parsedAddress = (emailAddress: string): string | undefined => {
}
export const createNewsletterEmail = async (
userId: string
userId: string,
confirmationCode?: string
): Promise<NewsletterEmail> => {
const user = await userRepository.findOne({
where: { id: userId },
@ -36,7 +37,8 @@ export const createNewsletterEmail = async (
(t) =>
t.getRepository(NewsletterEmail).save({
address: emailAddress,
user: user,
user,
confirmationCode,
}),
undefined,
userId
@ -92,7 +94,7 @@ export const updateConfirmationCode = async (
return !!result.affected
}
export const getNewsletterEmail = async (
export const findNewsletterEmail = async (
emailAddress: string
): Promise<NewsletterEmail | null> => {
const address = parsedAddress(emailAddress)
@ -119,3 +121,14 @@ const createRandomEmailAddress = (userName: string, length: number): string => {
*/
return `${userName}-${nanoid(length)}e@${inbox}.omnivore.app`
}
export const getNewsletterEmailById = async (
id: string,
userId: string
): Promise<NewsletterEmail | null> => {
return authTrx(
(t) => t.getRepository(NewsletterEmail).findOneBy({ id }),
undefined,
userId
)
}

View file

@ -0,0 +1,7 @@
import { Profile } from '../entity/profile'
import { User } from '../entity/user'
import { getRepository } from '../repository'
export const findProfile = async (user: User): Promise<Profile | null> => {
return getRepository(Profile).findOneBy({ user: { id: user.id } })
}

View file

@ -181,3 +181,22 @@ export const unsubscribeAll = async (
logger.info('Failed to unsubscribe all', error)
}
}
export const createSubscription = async (
userId: string,
name: string,
newsletterEmail?: NewsletterEmail,
status = SubscriptionStatus.Active,
unsubscribeMailTo?: string,
subscriptionType = SubscriptionType.Newsletter
): Promise<Subscription> => {
return getRepository(Subscription).save({
user: { id: userId },
name,
newsletterEmail,
status,
unsubscribeMailTo,
lastFetchedAt: new Date(),
type: subscriptionType,
})
}

View file

@ -0,0 +1,25 @@
import { User } from '../entity/user'
import { authTrx } from '../repository'
import { userRepository } from '../repository/user'
export const deleteUser = async (userId: string) => {
await authTrx(
async (t) => {
await t.withRepository(userRepository).delete(userId)
},
undefined,
userId
)
}
export const updateUser = async (userId: string, update: Partial<User>) => {
await authTrx(
async (t) => t.getRepository(User).update(userId, update),
undefined,
userId
)
}
export const findUser = async (id: string): Promise<User | null> => {
return userRepository.findOneBy({ id })
}

View file

@ -1,21 +1,22 @@
import { FindOptionsWhere } from 'typeorm'
import { UserDeviceToken } from '../entity/user_device_tokens'
import { env } from '../env'
import { authTrx } from '../repository'
import { analytics } from '../utils/analytics'
export const getDeviceToken = async (
export const findDeviceTokenById = async (
id: string
): Promise<UserDeviceToken | null> => {
return authTrx((t) => t.getRepository(UserDeviceToken).findOneBy({ id }))
}
export const getDeviceTokenByToken = async (
export const findDeviceTokenByToken = async (
token: string
): Promise<UserDeviceToken | null> => {
return authTrx((t) => t.getRepository(UserDeviceToken).findOneBy({ token }))
}
export const getDeviceTokensByUserId = async (
export const findDeviceTokensByUserId = async (
userId: string
): Promise<UserDeviceToken[]> => {
return authTrx((t) =>
@ -63,3 +64,16 @@ export const deleteDeviceToken = async (
return !!result.affected
})
}
export const deleteDeviceTokens = async (
userId: string,
criteria: string[] | FindOptionsWhere<UserDeviceToken>
) => {
return authTrx(
async (t) => {
await t.getRepository(UserDeviceToken).delete(criteria)
},
undefined,
userId
)
}

View file

@ -0,0 +1,27 @@
import { DeepPartial, EntityManager } from 'typeorm'
import { Webhook } from '../entity/webhook'
import { authTrx } from '../repository'
export const createWebhooks = async (
webhooks: DeepPartial<Webhook>[],
userId?: string,
entityManager?: EntityManager
) => {
return authTrx(
(tx) => tx.getRepository(Webhook).save(webhooks),
entityManager,
userId
)
}
export const createWebhook = async (
webhook: DeepPartial<Webhook>,
userId?: string,
entityManager?: EntityManager
) => {
return authTrx(
(tx) => tx.getRepository(Webhook).save(webhook),
entityManager,
userId
)
}

View file

@ -1,20 +1,18 @@
import Postgrator from 'postgrator'
import { FindOptionsWhere } from 'typeorm'
import { DeepPartial } from 'typeorm'
import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
import { appDataSource } from '../src/data_source'
import { Integration } from '../src/entity/integration'
import { Label } from '../src/entity/label'
import { NewsletterEmail } from '../src/entity/newsletter_email'
import { Profile } from '../src/entity/profile'
import { LibraryItem } from '../src/entity/library_item'
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 { SubscriptionStatus, SubscriptionType } from '../src/generated/graphql'
import { getRepository, setClaims } from '../src/repository'
import { getRepository } from '../src/repository'
import { userRepository } from '../src/repository/user'
import { createUser } from '../src/services/create_user'
import { Filter } from "../src/entity/filter"
import { createLibraryItem } from '../src/services/library_item'
import { createDeviceToken } from '../src/services/user_device_tokens'
const runMigrations = async () => {
const migrationDirectory = __dirname + '/../../db/migrations'
@ -63,13 +61,6 @@ export const createTestConnection = async (): Promise<void> => {
await appDataSource.initialize()
}
export const deleteTestUser = async (userId: string) => {
await appDataSource.transaction(async (t) => {
await setClaims(t, userId)
await t.getRepository(User).delete(userId)
})
}
export const deleteFiltersFromUser = async (userId: string) => {
await AppDataSource.transaction(async (t) => {
await setClaims(t, userId)
@ -105,7 +96,7 @@ export const createTestUser = async (
}
export const createUserWithoutProfile = async (name: string): Promise<User> => {
return getRepository(User).save({
return userRepository.save({
source: 'GOOGLE',
sourceUserId: 'fake-user-id-' + name,
email: `${name}@omnivore.app`,
@ -113,10 +104,6 @@ export const createUserWithoutProfile = async (name: string): Promise<User> => {
})
}
export const getProfile = async (user: User): Promise<Profile | null> => {
return getRepository(Profile).findOneBy({ user: { id: user.id } })
}
export const createTestReminder = async (
user: User,
pageId?: string
@ -132,107 +119,24 @@ export const getReminder = async (id: string): Promise<Reminder | null> => {
return getRepository(Reminder).findOneBy({ id })
}
export const createTestNewsletterEmail = async (
user: User,
emailAddress?: string,
confirmationCode?: string
): Promise<NewsletterEmail> => {
return getRepository(NewsletterEmail).save({
user: user,
address: emailAddress,
confirmationCode: confirmationCode,
})
}
export const getNewsletterEmail = async (
id: string
): Promise<NewsletterEmail | null> => {
return getRepository(NewsletterEmail).findOneBy({ id })
}
export const createTestDeviceToken = async (
user: User
): Promise<UserDeviceToken> => {
return getRepository(UserDeviceToken).save({
user: user,
token: 'Test token',
})
return createDeviceToken(user.id, 'fake-token')
}
export const getDeviceToken = async (
id: string
): Promise<UserDeviceToken | null> => {
return getRepository(UserDeviceToken).findOneBy({ id })
}
export const getUser = async (id: string): Promise<User | null> => {
return userRepository.findOneBy({ id })
}
export const createTestLabel = async (
user: User,
name: string,
color: string
): Promise<Label> => {
return getRepository(Label).save({
user,
name,
color,
})
}
export const createTestSubscription = async (
user: User,
name: string,
newsletterEmail?: NewsletterEmail,
status = SubscriptionStatus.Active,
unsubscribeMailTo?: string,
subscriptionType = SubscriptionType.Newsletter
): Promise<Subscription> => {
return getRepository(Subscription).save({
user,
name,
newsletterEmail,
status,
unsubscribeMailTo,
lastFetchedAt: new Date(),
type: subscriptionType,
})
}
export const deleteTestLabels = async (
export const createTestLibraryItem = async (
userId: string,
criteria: string[] | FindOptionsWhere<Label>
) => {
await appDataSource.transaction(async (t) => {
await setClaims(t, userId)
await t.getRepository(Label).delete(criteria)
})
}
labels?: Label[]
): Promise<LibraryItem> => {
const item: DeepPartial<LibraryItem> = {
user: { id: userId },
title: 'test title',
originalContent: '<p>test content</p>',
originalUrl: 'https://blog.omnivore.app/test-url',
slug: 'test-with-omnivore',
labels,
}
export const deleteTestIntegrations = async (
userId: string,
criteria: string[] | FindOptionsWhere<Integration>
) => {
await appDataSource.transaction(async (t) => {
await setClaims(t, userId)
await t.getRepository(Integration).delete(criteria)
})
}
export const updateTestUser = async (userId: string, update: Partial<User>) => {
await appDataSource.transaction(async (t) => {
await setClaims(t, userId)
await t.getRepository(User).update(userId, update)
})
}
export const deleteTestDeviceTokens = async (
userId: string,
criteria: string[] | FindOptionsWhere<UserDeviceToken>
) => {
await appDataSource.transaction(async (t) => {
await setClaims(t, userId)
await t.getRepository(UserDeviceToken).delete(criteria)
})
return createLibraryItem(item, userId)
}

View file

@ -1,8 +1,9 @@
import { createTestUser, deleteTestUser } from '../db'
import { graphqlRequest, request } from '../util'
import { User } from '../../src/entity/user'
import { hashPassword } from '../../src/utils/auth'
import 'mocha'
import { User } from '../../src/entity/user'
import { deleteUser } from '../../src/services/user'
import { hashPassword } from '../../src/utils/auth'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('Sanitize Directive', () => {
const correctPassword = 'fakePassword'
@ -21,7 +22,7 @@ describe('Sanitize Directive', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('Update user with a bio that is too long', () => {

View file

@ -2,8 +2,9 @@ import { expect } from 'chai'
import supertest from 'supertest'
import { ApiKey } from '../../src/entity/api_key'
import { User } from '../../src/entity/user'
import { getRepository } from '../../src/repository'
import { createTestUser, deleteTestUser } from '../db'
import { findApiKeys } from '../../src/services/api_key'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
const testAPIKey = (apiKey: string): supertest.Test => {
@ -44,7 +45,7 @@ describe('Api Key resolver', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('generate api key', () => {
@ -180,10 +181,7 @@ describe('Api Key resolver', () => {
}
`
apiKeys = await getRepository(ApiKey).find({
select: ['id', 'name'],
where: { user: { id: user.id } },
})
apiKeys = await findApiKeys(user.id, undefined, ['id', 'name'])
})
it('should get api keys', async () => {

View file

@ -26,11 +26,11 @@ import {
findLibraryItemByUrl,
updateLibraryItem
} from '../../src/services/library_item'
import { deleteUser } from '../../src/services/user'
import * as createTask from '../../src/utils/createTask'
import * as uploads from '../../src/utils/uploads'
import { createTestUser, deleteTestUser } from '../db'
import { createTestLibraryItem, createTestUser } from '../db'
import {
createTestLibraryItem,
generateFakeUuid,
graphqlRequest,
request
@ -99,47 +99,6 @@ const createArticleQuery = (
`
}
const articlesQuery = (after = '') => {
return `
query {
articles(
sharedOnly: ${false}
after: "${after}"
first: 5
query: "") {
... on ArticlesSuccess {
edges {
cursor
node {
id
url
linkId
createdAt
updatedAt
originalArticleUrl
labels {
id
name
color
}
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
totalCount
}
}
... on ArticlesError {
errorCodes
}
}
}
`
}
const getArticleQuery = (slug: string) => {
return `
query {
@ -384,7 +343,7 @@ describe('Article API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('CreateArticle', () => {
@ -570,7 +529,7 @@ describe('Article API', () => {
})
after(async () => {
await deleteLibraryItemById(url, user.id)
await deleteLibraryItemByUrl(url, user.id)
})
it('it should return that page in the GetArticles Query', async () => {
@ -581,14 +540,14 @@ describe('Article API', () => {
// Save a link, then archive it
let allLinks = await graphqlRequest(
articlesQuery(''),
searchQuery(''),
authToken
).expect(200)
const justSavedId = allLinks.body.data.articles.edges[0].node.id
await archiveLink(authToken, justSavedId)
// test the negative case, ensuring the archive link wasn't returned
allLinks = await graphqlRequest(articlesQuery(''), authToken).expect(
allLinks = await graphqlRequest(searchQuery(''), authToken).expect(
200
)
expect(allLinks.body.data.articles.edges[0]?.node?.url).to.not.eq(url)
@ -599,7 +558,7 @@ describe('Article API', () => {
authToken
).expect(200)
allLinks = await graphqlRequest(articlesQuery(''), authToken).expect(
allLinks = await graphqlRequest(searchQuery(''), authToken).expect(
200
)
expect(allLinks.body.data.articles.edges[0].node.url).to.eq(url)
@ -1201,12 +1160,7 @@ describe('Article API', () => {
mutation {
setFavoriteArticle(id: "${articleId}") {
... on SetFavoriteArticleSuccess {
favoriteArticle {
id
labels {
name
}
}
success
}
... on SetFavoriteArticleError {
errorCodes
@ -1234,17 +1188,10 @@ describe('Article API', () => {
})
it('favorites the article', async () => {
const res = await graphqlRequest(
await graphqlRequest(
setFavoriteArticleQuery(articleId),
authToken
).expect(200)
console.log(res.body.data.setFavoriteArticle.favoriteArticle)
expect(res.body.data.setFavoriteArticle.favoriteArticle.id).to.eq(
articleId
)
expect(
res.body.data.setFavoriteArticle.favoriteArticle.labels[0].name
).to.eq('Favorites')
const item = await findLibraryItemById(articleId, user.id)
expect(item?.labels?.map((l) => l.name)).to.eql(['Favorites'])

View file

@ -8,8 +8,9 @@ import {
CreateArticleSavingRequestErrorCode,
} from '../../src/generated/graphql'
import { findLibraryItemByUrl } from '../../src/services/library_item'
import { deleteUser } from '../../src/services/user'
import * as createTask from '../../src/utils/createTask'
import { createTestUser, deleteTestUser } from '../db'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
const articleSavingRequestQuery = ({
@ -73,7 +74,7 @@ describe('ArticleSavingRequest API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
sinon.restore()
})

View file

@ -5,8 +5,10 @@ import sinon, { SinonFakeTimers } from 'sinon'
import { Feature } from '../../src/entity/feature'
import { User } from '../../src/entity/user'
import { env } from '../../src/env'
import { getRepository } from '../../src/repository'
import { createTestUser, deleteTestUser } from '../db'
import { userRepository } from '../../src/repository/user'
import { createFeature, createFeatures, deleteFeature } from '../../src/services/features'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('features resolvers', () => {
@ -24,7 +26,7 @@ describe('features resolvers', () => {
})
after(async () => {
await deleteTestUser(loginUser.id)
await deleteUser(loginUser.id)
})
describe('optInFeature API', () => {
@ -64,9 +66,7 @@ describe('features resolvers', () => {
context('when user is the first 1500 users', () => {
after(async () => {
// reset feature
await getRepository(Feature).delete({
user: { id: loginUser.id },
})
await deleteFeature([], loginUser.id)
})
it('opts in to the feature', async () => {
@ -110,7 +110,7 @@ describe('features resolvers', () => {
}
})
users = await getRepository(User).save(usersToSave)
users = await userRepository.save(usersToSave)
const features = users.map((user) => {
return {
@ -120,16 +120,14 @@ describe('features resolvers', () => {
}
})
await getRepository(Feature).save(features)
await createFeatures(features, loginUser.id)
})
after(async () => {
// reset opt-in users
Promise.all(users.map((user) => deleteTestUser(user.id)))
Promise.all(users.map((user) => deleteUser(user.id)))
// reset feature
await getRepository(Feature).delete({
name: featureName,
})
await deleteFeature({ name: featureName }, loginUser.id)
})
it('does not opt in to the feature', async () => {
@ -160,18 +158,19 @@ describe('features resolvers', () => {
context('when user is already opted in', () => {
before(async () => {
// opt in
await getRepository(Feature).save({
user: { id: loginUser.id },
name: featureName,
grantedAt: new Date(),
})
await createFeature(
{
user: { id: loginUser.id },
name: featureName,
grantedAt: new Date(),
},
loginUser.id
)
})
after(async () => {
// reset feature
await getRepository(Feature).delete({
user: { id: loginUser.id },
})
await deleteFeature([], loginUser.id)
})
it('returns the feature', async () => {

View file

@ -1,6 +1,5 @@
import { createTestUser, deleteTestUser } from '../db'
import { createTestLibraryItem, createTestUser } from '../db'
import {
createTestLibraryItem,
generateFakeUuid,
graphqlRequest,
request,
@ -10,8 +9,8 @@ import { expect } from 'chai'
import 'mocha'
import { User } from '../../src/entity/user'
import chaiString from 'chai-string'
import { createPubSubClient } from '../../src/pubsub'
import { updateLibraryItem } from '../../src/services/library_item'
import { deleteUser } from '../../src/services/user'
chai.use(chaiString)
@ -155,7 +154,7 @@ describe('Highlights API', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
context('createHighlightMutation', () => {

View file

@ -5,9 +5,15 @@ import sinonChai from 'sinon-chai'
import { Integration } from '../../src/entity/integration'
import { User } from '../../src/entity/user'
import { SetIntegrationErrorCode } from '../../src/generated/graphql'
import { getRepository } from '../../src/repository'
import {
createIntegration,
deleteIntegrations,
findIntegration,
updateIntegration,
} from '../../src/services/integrations'
import { READWISE_API_URL } from '../../src/services/integrations/readwise'
import { createTestUser, deleteTestIntegrations, deleteTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { generateFakeUuid, graphqlRequest, request } from '../util'
chai.use(sinonChai)
@ -27,7 +33,7 @@ describe('Integrations resolvers', () => {
})
after(async () => {
await deleteTestUser(loginUser.id)
await deleteUser(loginUser.id)
})
describe('setIntegration API', () => {
@ -110,7 +116,7 @@ describe('Integrations resolvers', () => {
})
afterEach(async () => {
await deleteTestIntegrations(loginUser.id, {
await deleteIntegrations(loginUser.id, {
user: { id: loginUser.id },
name: integrationName,
})
@ -129,9 +135,9 @@ describe('Integrations resolvers', () => {
query(integrationId, integrationName, token),
authToken
)
const integration = await getRepository(Integration).findOneBy({
const integration = await findIntegration({
id: res.body.data.setIntegration.integration.id,
})
}, loginUser.id)
expect(integration?.taskName).not.to.be.null
})
})
@ -162,17 +168,17 @@ describe('Integrations resolvers', () => {
before(async () => {
otherUser = await createTestUser('otherUser')
existingIntegration = await getRepository(Integration).save({
existingIntegration = await createIntegration({
user: { id: otherUser.id },
name: 'READWISE',
token: 'fakeToken',
})
}, otherUser.id)
integrationId = existingIntegration.id
})
after(async () => {
await deleteTestUser(otherUser.id)
await deleteTestIntegrations(otherUser.id, [existingIntegration.id])
await deleteUser(otherUser.id)
await deleteIntegrations(otherUser.id, [existingIntegration.id])
})
it('returns Unauthorized error code', async () => {
@ -188,16 +194,16 @@ describe('Integrations resolvers', () => {
context('when integration belongs to the user', () => {
before(async () => {
existingIntegration = await getRepository(Integration).save({
existingIntegration = await createIntegration({
user: { id: loginUser.id },
name: 'READWISE',
token: 'fakeToken',
})
}, loginUser.id)
integrationId = existingIntegration.id
})
after(async () => {
await deleteTestIntegrations(loginUser.id, [existingIntegration.id])
await deleteIntegrations(loginUser.id, [existingIntegration.id])
})
context('when enable is false', () => {
@ -206,10 +212,10 @@ describe('Integrations resolvers', () => {
})
afterEach(async () => {
await getRepository(Integration).update(existingIntegration.id, {
await updateIntegration(existingIntegration.id, {
taskName: 'some task name',
enabled: true,
})
}, loginUser.id)
})
it('disables integration', async () => {
@ -226,9 +232,9 @@ describe('Integrations resolvers', () => {
query(integrationId, integrationName, token, enabled),
authToken
)
const integration = await getRepository(Integration).findOneBy({
const integration = await findIntegration({
id: res.body.data.setIntegration.integration.id,
})
}, loginUser.id)
expect(integration?.taskName).to.be.null
})
})
@ -239,10 +245,10 @@ describe('Integrations resolvers', () => {
})
afterEach(async () => {
await getRepository(Integration).update(existingIntegration.id, {
await updateIntegration(existingIntegration.id, {
taskName: null,
enabled: false,
})
}, loginUser.id)
})
it('enables integration', async () => {
@ -259,9 +265,9 @@ describe('Integrations resolvers', () => {
query(integrationId, integrationName, token, enabled),
authToken
)
const integration = await getRepository(Integration).findOneBy({
const integration = await findIntegration({
id: res.body.data.setIntegration.integration.id,
})
}, loginUser.id)
expect(integration?.taskName).not.to.be.null
})
})
@ -288,15 +294,15 @@ describe('Integrations resolvers', () => {
let existingIntegration: Integration
before(async () => {
existingIntegration = await getRepository(Integration).save({
existingIntegration = await createIntegration({
user: { id: loginUser.id },
name: 'READWISE',
token: 'fakeToken',
})
}, loginUser.id)
})
after(async () => {
await deleteTestIntegrations(loginUser.id, [existingIntegration.id])
await deleteIntegrations(loginUser.id, [existingIntegration.id])
})
it('returns all integrations', async () => {
@ -334,12 +340,12 @@ describe('Integrations resolvers', () => {
let existingIntegration: Integration
beforeEach(async () => {
existingIntegration = await getRepository(Integration).save({
existingIntegration = await createIntegration({
user: { id: loginUser.id },
name: 'READWISE',
token: 'fakeToken',
taskName: 'some task name',
})
}, loginUser.id)
})
it('deletes the integration and cloud task', async () => {
@ -347,9 +353,9 @@ describe('Integrations resolvers', () => {
query(existingIntegration.id),
authToken
)
const integration = await getRepository(Integration).findOneBy({
const integration = await findIntegration({
id: existingIntegration.id,
})
}, loginUser.id)
expect(res.body.data.deleteIntegration.integration).to.be.an('object')
expect(res.body.data.deleteIntegration.integration.id).to.eql(
@ -377,15 +383,15 @@ describe('Integrations resolvers', () => {
context('when integration exists', () => {
before(async () => {
existingIntegration = await getRepository(Integration).save({
existingIntegration = await createIntegration({
user: { id: loginUser.id },
name: 'POCKET',
token: 'fakeToken',
})
}, loginUser.id)
})
after(async () => {
await deleteTestIntegrations(loginUser.id, [existingIntegration.id])
await deleteIntegrations(loginUser.id, [existingIntegration.id])
})
it('returns success and starts cloud task', async () => {
@ -394,9 +400,9 @@ describe('Integrations resolvers', () => {
authToken
).expect(200)
expect(res.body.data.importFromIntegration.success).to.be.true
const integration = await getRepository(Integration).findOneBy({
const integration = await findIntegration({
id: existingIntegration.id,
})
}, loginUser.id)
expect(integration?.taskName).not.to.be.null
})
})

View file

@ -10,22 +10,14 @@ import {
createHighlight,
findHighlightById,
} from '../../src/services/highlights'
import { createLabel, deleteLabels } from '../../src/services/labels'
import {
deleteLibraryItemById,
findLibraryItemById,
} from '../../src/services/library_item'
import {
createTestLabel,
createTestUser,
deleteTestLabels,
deleteTestUser,
} from '../db'
import {
createTestLibraryItem,
generateFakeUuid,
graphqlRequest,
request,
} from '../util'
import { deleteUser } from '../../src/services/user'
import { createTestLibraryItem, createTestUser } from '../db'
import { generateFakeUuid, graphqlRequest, request } from '../util'
describe('Labels API', () => {
let user: User
@ -42,7 +34,7 @@ describe('Labels API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('GET labels', () => {
@ -51,16 +43,16 @@ describe('Labels API', () => {
before(async () => {
// create testing labels
const label1 = await createTestLabel(user, 'label_1', '#ffffff')
const label2 = await createTestLabel(user, 'label_2', '#eeeeee')
const label1 = await createLabel(user.id, 'label_1', '#ffffff')
const label2 = await createLabel(user.id, 'label_2', '#eeeeee')
labels = [label1, label2]
})
after(async () => {
// clean up
await deleteTestLabels(
user.id,
labels.map((l) => l.id)
await deleteLabels(
labels.map((l) => l.id),
user.id
)
})
@ -151,7 +143,7 @@ describe('Labels API', () => {
after(async () => {
// clean up
await deleteTestLabels(user.id, { name })
await deleteLabels({ name }, user.id)
})
it('should create label', async () => {
@ -167,12 +159,12 @@ describe('Labels API', () => {
let existingLabel: Label
before(async () => {
existingLabel = await createTestLabel(user, 'label3', '#ffffff')
existingLabel = await createLabel(user.id, 'label3', '#ffffff')
name = existingLabel.name
})
after(async () => {
await deleteTestLabels(user.id, [existingLabel.id])
await deleteLabels([existingLabel.id], user.id)
})
it('should return error code LABEL_ALREADY_EXISTS', async () => {
@ -226,8 +218,8 @@ describe('Labels API', () => {
context('when label is not used', () => {
before(async () => {
toDeleteLabel = await createTestLabel(
user,
toDeleteLabel = await createLabel(
user.id,
'label not in use',
'#ffffff'
)
@ -245,7 +237,7 @@ describe('Labels API', () => {
let item: LibraryItem
before(async () => {
toDeleteLabel = await createTestLabel(user, 'page label', '#ffffff')
toDeleteLabel = await createLabel(user.id, 'page label', '#ffffff')
labelId = toDeleteLabel.id
item = await createTestLibraryItem(user.id, [toDeleteLabel])
})
@ -268,8 +260,8 @@ describe('Labels API', () => {
before(async () => {
item = await createTestLibraryItem(user.id)
toDeleteLabel = await createTestLabel(
user,
toDeleteLabel = await createLabel(
user.id,
'highlight label',
'#ffffff'
)
@ -334,17 +326,17 @@ describe('Labels API', () => {
before(async () => {
// create testing labels
const label1 = await createTestLabel(user, 'label_1', '#ffffff')
const label2 = await createTestLabel(user, 'label_2', '#eeeeee')
const label1 = await createLabel(user.id, 'label_1', '#ffffff')
const label2 = await createLabel(user.id, 'label_2', '#eeeeee')
labels = [label1, label2]
item = await createTestLibraryItem(user.id)
})
after(async () => {
// clean up
await deleteTestLabels(
user.id,
labels.map((l) => l.id)
await deleteLabels(
labels.map((l) => l.id),
user.id
)
await deleteLibraryItemById(item.id)
})
@ -462,14 +454,14 @@ describe('Labels API', () => {
let toUpdateLabel: Label
before(async () => {
toUpdateLabel = await createTestLabel(user, 'label5', '#ffffff')
toUpdateLabel = await createLabel(user.id, 'label5', '#ffffff')
labelId = toUpdateLabel.id
name = 'Updated label'
color = '#aabbcc'
})
after(async () => {
await deleteTestLabels(user.id, [toUpdateLabel.id])
await deleteLabels([toUpdateLabel.id], user.id)
})
it('should return the updated label', async () => {
@ -537,17 +529,17 @@ describe('Labels API', () => {
before(async () => {
// create testing labels
const label1 = await createTestLabel(user, 'label_1', '#ffffff')
const label2 = await createTestLabel(user, 'label_2', '#eeeeee')
const label1 = await createLabel(user.id, 'label_1', '#ffffff')
const label2 = await createLabel(user.id, 'label_2', '#eeeeee')
labels = [label1, label2]
item = await createTestLibraryItem(user.id)
})
after(async () => {
// clean up
await deleteTestLabels(
user.id,
labels.map((l) => l.id)
await deleteLabels(
labels.map((l) => l.id),
user.id
)
await deleteLibraryItemById(item.id)
})
@ -665,16 +657,16 @@ describe('Labels API', () => {
before(async () => {
// create testing labels
for (let i = 0; i < 5; i++) {
const label = await createTestLabel(user, `label_${i}`, '#ffffff')
const label = await createLabel(user.id, `label_${i}`, '#ffffff')
labels.push(label)
}
})
after(async () => {
// clean up
await deleteTestLabels(
user.id,
labels.map((l) => l.id)
await deleteLabels(
labels.map((l) => l.id),
user.id
)
})

View file

@ -8,12 +8,12 @@ import {
} from '../../src/generated/graphql'
import { getRepository } from '../../src/repository'
import {
createTestNewsletterEmail,
createTestSubscription,
createTestUser,
deleteTestUser,
getNewsletterEmail,
} from '../db'
createNewsletterEmail,
findNewsletterEmail,
} from '../../src/services/newsletters'
import { createSubscription } from '../../src/services/subscriptions'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { generateFakeUuid, graphqlRequest, request } from '../util'
describe('Newsletters API', () => {
@ -32,7 +32,7 @@ describe('Newsletters API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('Get newsletter emails', () => {
@ -61,18 +61,18 @@ describe('Newsletters API', () => {
before(async () => {
// create test newsletter emails
const newsletterEmail1 = await createTestNewsletterEmail(
user,
const newsletterEmail1 = await createNewsletterEmail(
user.id,
'Test_email_address_1@omnivore.app'
)
const newsletterEmail2 = await createTestNewsletterEmail(
user,
const newsletterEmail2 = await createNewsletterEmail(
user.id,
'Test_email_address_2@omnivore.app'
)
newsletterEmails = [newsletterEmail1, newsletterEmail2]
// create testing subscriptions
await createTestSubscription(user, 'sub', newsletterEmail2)
await createSubscription(user.id, 'sub', newsletterEmail2)
})
after(async () => {
@ -118,14 +118,14 @@ describe('Newsletters API', () => {
before(async () => {
// create test newsletter emails
newsletterEmail = await createTestNewsletterEmail(
user,
newsletterEmail = await createNewsletterEmail(
user.id,
'Test_email_address_1@omnivore.app'
)
// create unsubscribed subscriptions
await createTestSubscription(
user,
await createSubscription(
user.id,
'sub',
newsletterEmail,
SubscriptionStatus.Unsubscribed
@ -181,7 +181,7 @@ describe('Newsletters API', () => {
it('responds with status code 200', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
const newsletterEmail = await getNewsletterEmail(
const newsletterEmail = await findNewsletterEmail(
response.body.data.createNewsletterEmail.id
)
expect(newsletterEmail).not.to.be.undefined
@ -227,8 +227,8 @@ describe('Newsletters API', () => {
context('when newsletter email exists', () => {
before(async () => {
// create test newsletter emails
const newsletterEmail = await createTestNewsletterEmail(
user,
const newsletterEmail = await createNewsletterEmail(
user.id,
'Test_email_address_1@omnivore.app'
)
newsletterEmailId = newsletterEmail.id
@ -241,7 +241,7 @@ describe('Newsletters API', () => {
it('responds with status code 200', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
const newsletterEmail = await getNewsletterEmail(
const newsletterEmail = await findNewsletterEmail(
response.body.data.deleteNewsletterEmail.newsletterEmail.id
)
expect(newsletterEmail).to.be.null

View file

@ -2,7 +2,8 @@ import { expect } from 'chai'
import 'mocha'
import { User } from '../../src/entity/user'
import { findLibraryItemById } from '../../src/services/library_item'
import { createTestUser, deleteTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('PopularReads API', () => {
@ -36,7 +37,7 @@ describe('PopularReads API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('addPopularRead', () => {

View file

@ -5,8 +5,9 @@ import { NewsletterEmail } from '../../src/entity/newsletter_email'
import { ReceivedEmail } from '../../src/entity/received_email'
import { User } from '../../src/entity/user'
import { getRepository } from '../../src/repository'
import { deleteUser } from '../../src/services/user'
import * as sendEmail from '../../src/utils/sendEmail'
import { createTestUser, deleteTestUser } from '../db'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('Recent Emails Resolver', () => {
@ -59,7 +60,7 @@ describe('Recent Emails Resolver', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('recentEmails', () => {
@ -162,8 +163,8 @@ describe('Recent Emails Resolver', () => {
user2Auth = res.body.authToken
})
after(async () => {
await deleteTestUser(user2.id)
await deleteTestUser(user3.id)
await deleteUser(user2.id)
await deleteUser(user3.id)
})
before(async () => {

View file

@ -3,7 +3,8 @@ import 'mocha'
import { SearchHistory } from '../../src/entity/search_history'
import { User } from '../../src/entity/user'
import { getRepository } from '../../src/repository'
import { createTestUser, deleteTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('recent_searches resolver', () => {
@ -21,7 +22,7 @@ describe('recent_searches resolver', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('recentSearches API', () => {

View file

@ -9,18 +9,14 @@ import {
ReminderErrorCode,
UpdateReminderErrorCode,
} from '../../src/generated/graphql'
import {
createTestReminder,
createTestUser,
deleteTestUser,
getReminder,
} from '../db'
import { deleteUser } from '../../src/services/user'
import {
createTestLibraryItem,
generateFakeUuid,
graphqlRequest,
request,
} from '../util'
createTestReminder,
createTestUser,
getReminder,
} from '../db'
import { generateFakeUuid, graphqlRequest, request } from '../util'
xdescribe('Reminders API', () => {
let authToken: string
@ -44,7 +40,7 @@ xdescribe('Reminders API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('Get reminder', () => {

View file

@ -5,8 +5,9 @@ import { ContentDisplayReport } from '../../src/entity/reports/content_display_r
import { User } from '../../src/entity/user'
import { ReportType } from '../../src/generated/graphql'
import { getRepository } from '../../src/repository'
import { createTestUser, deleteTestUser } from '../db'
import { createTestLibraryItem, graphqlRequest, request } from '../util'
import { deleteUser } from '../../src/services/user'
import { createTestLibraryItem, createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('Report API', () => {
let user: User
@ -28,7 +29,7 @@ describe('Report API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('reportItem', () => {

View file

@ -3,7 +3,8 @@ import 'mocha'
import { Rule, RuleAction, RuleActionType } from '../../src/entity/rule'
import { User } from '../../src/entity/user'
import { authTrx, getRepository } from '../../src/repository'
import { createTestUser, deleteTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('Rules Resolver', () => {
@ -24,7 +25,7 @@ describe('Rules Resolver', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('set rules', () => {

View file

@ -1,7 +1,8 @@
import { createTestUser, deleteTestUser } from '../db'
import { graphqlRequest, request } from '../util'
import 'mocha'
import { User } from '../../src/entity/user'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('Send Install Instructions API', () => {
let authToken: string
@ -19,7 +20,7 @@ describe('Send Install Instructions API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('Send install instructions', () => {

View file

@ -10,12 +10,15 @@ import {
SubscriptionType,
} from '../../src/generated/graphql'
import {
createSubscription,
unsubscribe,
UNSUBSCRIBE_EMAIL_TEXT
} from '../../src/services/subscriptions'
import { authTrx, getRepository } from '../../src/repository'
import { getRepository } from '../../src/repository'
import { createNewsletterEmail } from '../../src/services/newsletters'
import { deleteUser } from '../../src/services/user'
import * as sendEmail from '../../src/utils/sendEmail'
import { createTestSubscription, createTestUser, deleteTestUser } from '../db'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
chai.use(sinonChai)
@ -35,30 +38,21 @@ describe('Subscriptions API', () => {
authToken = res.body.authToken
// create test newsletter subscriptions
const newsletterEmail = await authTrx(
(t) =>
t.getRepository(NewsletterEmail).save({
user,
address: 'test@inbox.omnivore.app',
confirmationCode: 'test',
}),
undefined,
user.id
)
const newsletterEmail = await createNewsletterEmail(user.id)
// create testing newsletter subscriptions
const sub1 = await createTestSubscription(user, 'sub_1', newsletterEmail)
const sub2 = await createTestSubscription(user, 'sub_2', newsletterEmail)
const sub1 = await createSubscription(user.id, 'sub_1', newsletterEmail)
const sub2 = await createSubscription(user.id, 'sub_2', newsletterEmail)
// create a unsubscribed subscription
await createTestSubscription(
user,
await createSubscription(
user.id,
'sub_3',
newsletterEmail,
SubscriptionStatus.Unsubscribed
)
// create an rss feed subscription
const sub4 = await createTestSubscription(
user,
const sub4 = await createSubscription(
user.id,
'sub_4',
undefined,
SubscriptionStatus.Active,
@ -70,7 +64,7 @@ describe('Subscriptions API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('GET subscriptions', () => {
@ -313,8 +307,8 @@ describe('Subscriptions API', () => {
address: 'test_2@inbox.omnivore.app',
confirmationCode: 'test',
})
const subscription = await createTestSubscription(
user,
const subscription = await createSubscription(
user.id,
name,
newsletterEmail,
SubscriptionStatus.Active,

View file

@ -2,8 +2,9 @@ import { expect } from 'chai'
import 'mocha'
import { LibraryItem } from '../../src/entity/library_item'
import { User } from '../../src/entity/user'
import { createTestUser, deleteTestUser } from '../db'
import { createTestLibraryItem, graphqlRequest, request } from '../util'
import { deleteUser } from '../../src/services/user'
import { createTestLibraryItem, createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('Update API', () => {
let user: User
@ -23,7 +24,7 @@ describe('Update API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('update page', () => {

View file

@ -7,7 +7,8 @@ import {
deleteLibraryItemById,
findLibraryItemById,
} from '../../src/services/library_item'
import { createTestUser, deleteTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { generateFakeUuid, graphqlRequest, request } from '../util'
chai.use(chaiString)
@ -61,7 +62,7 @@ describe('uploadFileRequest API', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('UploadFileRequest', () => {

View file

@ -1,10 +1,11 @@
import { createTestUser, deleteTestUser } from '../db'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
import * as chai from 'chai'
import { expect } from 'chai'
import 'mocha'
import { User } from '../../src/entity/user'
import chaiString from 'chai-string'
import { deleteUser } from '../../src/services/user'
chai.use(chaiString)
@ -43,7 +44,7 @@ describe('uploadImportFile API', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('UploadImportFile', () => {

View file

@ -1,13 +1,15 @@
import { createTestUser, deleteTestUser, getProfile, getUser } from '../db'
import { graphqlRequest, request } from '../util'
import { expect } from 'chai'
import 'mocha'
import { User } from '../../src/entity/user'
import {
UpdateUserErrorCode,
UpdateUserProfileErrorCode,
} from '../../src/generated/graphql'
import { User } from '../../src/entity/user'
import { findProfile } from '../../src/services/profile'
import { deleteUser, findUser } from '../../src/services/user'
import { hashPassword } from '../../src/utils/auth'
import 'mocha'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('User API', () => {
const correctPassword = 'fakePassword'
@ -33,8 +35,8 @@ describe('User API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteTestUser(anotherUser.id)
await deleteUser(user.id)
await deleteUser(anotherUser.id)
})
describe('Update user', () => {
@ -96,7 +98,7 @@ describe('User API', () => {
it('updates user and responds with status code 200', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
const user = await getUser(response.body.data.updateUser.user.id)
const user = await findUser(response.body.data.updateUser.user.id)
expect(user?.name).to.eql(name)
})
})
@ -160,7 +162,7 @@ describe('User API', () => {
it('updates user profile and responds with 200', async () => {
await graphqlRequest(query, authToken).expect(200)
const profile = await getProfile(user)
const profile = await findProfile(user)
expect(profile?.username).to.eql(newUsername)
})
})
@ -196,7 +198,7 @@ describe('User API', () => {
context('when username exists', () => {
before(async () => {
userId = user.id
const profile = await getProfile(user)
const profile = await findProfile(user)
newUsername = profile?.username || 'new_username'
})

View file

@ -1,4 +1,4 @@
import { createTestUser, deleteTestUser } from '../db'
import { createTestUser } from '../db'
import { generateFakeUuid, graphqlRequest, request } from '../util'
import * as chai from 'chai'
import { expect } from 'chai'
@ -6,6 +6,7 @@ import 'mocha'
import { User } from '../../src/entity/user'
import chaiString from 'chai-string'
import { DeleteAccountErrorCode } from '../../src/generated/graphql'
import { deleteUser } from '../../src/services/user'
chai.use(chaiString)
@ -42,7 +43,7 @@ describe('the deleteAccount API', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
context('deleting a user that exists', () => {

View file

@ -4,13 +4,9 @@ import { User } from '../../src/entity/user'
import { UserDeviceToken } from '../../src/entity/user_device_tokens'
import { SetDeviceTokenErrorCode } from '../../src/generated/graphql'
import { getRepository } from '../../src/repository'
import {
createTestDeviceToken,
createTestUser,
deleteTestDeviceTokens,
deleteTestUser,
getDeviceToken,
} from '../db'
import { deleteUser } from '../../src/services/user'
import { deleteDeviceTokens, findDeviceTokenById } from '../../src/services/user_device_tokens'
import { createTestDeviceToken, createTestUser } from '../db'
import { generateFakeUuid, graphqlRequest, request } from '../util'
describe('Device tokens API', () => {
@ -33,7 +29,7 @@ describe('Device tokens API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('Set device token', () => {
@ -67,7 +63,7 @@ describe('Device tokens API', () => {
after(async () => {
// clean up
await deleteTestDeviceTokens(user.id, { user: { id: user.id } })
await deleteDeviceTokens(user.id, { user: { id: user.id } })
})
context('when id in input is not null', () => {
@ -79,7 +75,7 @@ describe('Device tokens API', () => {
it('responds with status code 200 and deletes the token', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
const deviceToken = await getDeviceToken(
const deviceToken = await findDeviceTokenById(
response.body.data.setDeviceToken.deviceToken.id
)
expect(deviceToken).to.be.null
@ -109,7 +105,7 @@ describe('Device tokens API', () => {
it('responds with status code 200 and creates the token', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
const deviceToken = await getDeviceToken(
const deviceToken = await findDeviceTokenById(
response.body.data.setDeviceToken.deviceToken.id
)
expect(deviceToken).not.to.be.null
@ -175,7 +171,7 @@ describe('Device tokens API', () => {
after(async () => {
// clean up
await deleteTestDeviceTokens(user.id, { token })
await deleteDeviceTokens(user.id, { token })
})
it('responds with status code 200 and returns all device tokens', async () => {

View file

@ -3,8 +3,10 @@ import 'mocha'
import { User } from '../../src/entity/user'
import { Webhook } from '../../src/entity/webhook'
import { WebhookEvent } from '../../src/generated/graphql'
import { authTrx, getRepository } from '../../src/repository'
import { createTestUser, deleteTestUser } from '../db'
import { getRepository } from '../../src/repository'
import { deleteUser } from '../../src/services/user'
import { createWebhooks } from '../../src/services/webhook'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
describe('Webhooks API', () => {
@ -21,28 +23,26 @@ describe('Webhooks API', () => {
authToken = res.body.authToken
// create test webhooks
await authTrx(
(t) =>
t.getRepository(Webhook).save([
{
url: 'http://localhost:3000/webhooks/test',
user: { id: user.id },
eventTypes: [WebhookEvent.PageCreated],
},
{
url: 'http://localhost:3000/webhooks/test',
user: { id: user.id },
eventTypes: [WebhookEvent.PageUpdated],
},
]),
undefined,
await createWebhooks(
[
{
url: 'http://localhost:3000/webhooks/test',
user: { id: user.id },
eventTypes: [WebhookEvent.PageCreated],
},
{
url: 'http://localhost:3000/webhooks/test',
user: { id: user.id },
eventTypes: [WebhookEvent.PageUpdated],
},
],
user.id
)
})
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('Get webhook', () => {

View file

@ -1,12 +1,13 @@
import { createTestUser, deleteTestUser } from '../db'
import { request } from '../util'
import { expect } from 'chai'
import nock from 'nock'
import 'mocha'
import { env } from '../../src/env'
import { User } from '../../src/entity/user'
import nock from 'nock'
import sinon from 'sinon'
import { User } from '../../src/entity/user'
import { env } from '../../src/env'
import { deleteUser } from '../../src/services/user'
import * as createTask from '../../src/utils/createTask'
import { createTestUser } from '../db'
import { request } from '../util'
describe('/article/save API', () => {
let user: User
@ -29,7 +30,7 @@ describe('/article/save API', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('POST /article/save', () => {

View file

@ -9,13 +9,14 @@ import { userRepository } from '../../src/repository/user'
import { AuthProvider } from '../../src/routers/auth/auth_types'
import { createPendingUserToken } from '../../src/routers/auth/jwt_helpers'
import { searchLibraryItems } from '../../src/services/library_item'
import { deleteUser, updateUser } from '../../src/services/user'
import {
comparePassword,
generateVerificationToken,
hashPassword,
} from '../../src/utils/auth'
import * as util from '../../src/utils/sendEmail'
import { createTestUser, deleteTestUser, updateTestUser } from '../db'
import { createTestUser } from '../db'
import { generateFakeUuid, request } from '../util'
chai.use(sinonChai)
@ -56,7 +57,7 @@ describe('auth router', () => {
afterEach(async () => {
const user = await getRepository(User).findOneBy({ name })
await deleteTestUser(user!.id)
await deleteUser(user!.id)
})
context('when confirmation email sent', () => {
@ -123,7 +124,7 @@ describe('auth router', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
it('redirects to sign up page with error code USER_EXISTS', async () => {
@ -190,7 +191,7 @@ describe('auth router', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
context('when email and password are valid', () => {
@ -216,13 +217,13 @@ describe('auth router', () => {
beforeEach(async () => {
fake = sinon.replace(util, 'sendEmail', sinon.fake.resolves(true))
await updateTestUser(user.id, { status: StatusType.Pending })
await updateUser(user.id, { status: StatusType.Pending })
email = user.email
password = correctPassword
})
afterEach(async () => {
await updateTestUser(user.id, { status: StatusType.Active })
await updateUser(user.id, { status: StatusType.Active })
sinon.restore()
})
@ -254,13 +255,13 @@ describe('auth router', () => {
context('when user has no password stored in db', async () => {
before(async () => {
await updateTestUser(user.id, { password: '' })
await updateUser(user.id, { password: '' })
email = user.email
password = user.password!
})
after(async () => {
await updateTestUser(user.id, { password })
await updateUser(user.id, { password })
})
it('redirects with error code WrongSource', async () => {
@ -301,7 +302,7 @@ describe('auth router', () => {
after(async () => {
sinon.restore()
await deleteTestUser(user.id)
await deleteUser(user.id)
})
context('when token is valid', () => {
@ -389,14 +390,14 @@ describe('auth router', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
context('when email is verified', () => {
let fake: (msg: MailDataRequired) => Promise<boolean>
before(async () => {
await updateTestUser(user.id, { status: StatusType.Active })
await updateUser(user.id, { status: StatusType.Active })
})
context('when reset password email sent', () => {
@ -438,7 +439,7 @@ describe('auth router', () => {
context('when email is not verified', () => {
before(async () => {
await updateTestUser(user.id, { status: StatusType.Pending })
await updateUser(user.id, { status: StatusType.Pending })
})
it('redirects to email-login page with error code PENDING_VERIFICATION', async () => {
@ -493,7 +494,7 @@ describe('auth router', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
context('when token is valid', () => {
@ -587,7 +588,7 @@ describe('auth router', () => {
afterEach(async () => {
const user = await userRepository.findOneByOrFail({ name })
await deleteTestUser(user.id)
await deleteUser(user.id)
})
it('adds popular reads to the library', async () => {

View file

@ -5,14 +5,12 @@ import sinon from 'sinon'
import { ReceivedEmail } from '../../src/entity/received_email'
import { User } from '../../src/entity/user'
import { getRepository } from '../../src/repository'
import { createNewsletterEmail } from '../../src/services/newsletters'
import { deleteUser } from '../../src/services/user'
import * as parser from '../../src/utils/parser'
import * as sendEmail from '../../src/utils/sendEmail'
import * as sendNotification from '../../src/utils/sendNotification'
import {
createTestNewsletterEmail,
createTestUser,
deleteTestUser,
} from '../db'
import { createTestUser } from '../db'
import { request } from '../util'
describe('Emails Router', () => {
@ -30,7 +28,7 @@ describe('Emails Router', () => {
// create test user and login
user = await createTestUser('fakeUser')
await createTestNewsletterEmail(user, newsletterEmail)
await createNewsletterEmail(user.id, newsletterEmail)
token = process.env.PUBSUB_VERIFICATION_TOKEN!
receivedEmail = await getRepository(ReceivedEmail).save({
user: { id: user.id },
@ -45,7 +43,7 @@ describe('Emails Router', () => {
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
sinon.restore()
})

View file

@ -12,11 +12,13 @@ import { env } from '../../src/env'
import { PubSubRequestBody } from '../../src/pubsub'
import { authTrx, getRepository } from '../../src/repository'
import { createHighlight, getHighlightUrl } from '../../src/services/highlights'
import { deleteIntegrations } from '../../src/services/integrations'
import { READWISE_API_URL } from '../../src/services/integrations/readwise'
import { deleteLibraryItemById } from '../../src/services/library_item'
import { createTestUser, deleteTestIntegrations, deleteTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
import { createTestLibraryItem, createTestUser } from '../db'
import { MockBucket } from '../mock_storage'
import { createTestLibraryItem, request } from '../util'
import { request } from '../util'
describe('Integrations routers', () => {
const baseUrl = '/svc/pubsub/integrations'
@ -35,7 +37,7 @@ describe('Integrations routers', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('sync with integrations', () => {
@ -174,7 +176,7 @@ describe('Integrations routers', () => {
})
after(async () => {
await deleteTestIntegrations(user.id, [integration.id])
await deleteIntegrations(user.id, [integration.id])
await deleteLibraryItemById(item.id)
})
@ -399,7 +401,7 @@ describe('Integrations routers', () => {
after(async () => {
sinon.restore()
await deleteTestIntegrations(user.id, [integration.id])
await deleteIntegrations(user.id, [integration.id])
})
context('when integration is pocket', () => {

View file

@ -3,11 +3,9 @@ import * as jwt from 'jsonwebtoken'
import 'mocha'
import { User } from '../../src/entity/user'
import { findLibraryItemById } from '../../src/services/library_item'
import {
createTestNewsletterEmail,
createTestUser,
deleteTestUser,
} from '../db'
import { createNewsletterEmail } from '../../src/services/newsletters'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { request } from '../util'
describe('PDF attachments Router', () => {
@ -20,13 +18,13 @@ describe('PDF attachments Router', () => {
// create test user and login
user = await createTestUser('fakeUser')
await createTestNewsletterEmail(user, newsletterEmail)
await createNewsletterEmail(user.id, newsletterEmail)
authToken = jwt.sign(newsletterEmail, process.env.JWT_SECRET || '')
})
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('upload', () => {

View file

@ -3,8 +3,9 @@ import 'mocha'
import nock from 'nock'
import { User } from '../../src/entity/user'
import { Webhook } from '../../src/entity/webhook'
import { authTrx } from '../../src/repository'
import { createTestUser, deleteTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
import { createWebhook } from '../../src/services/webhook'
import { createTestUser } from '../db'
import { request } from '../util'
describe('Webhooks Router', () => {
@ -22,21 +23,19 @@ describe('Webhooks Router', () => {
.post('/local/debug/fake-user-login')
.send({ fakeEmail: user.email })
webhook = await authTrx(
(t) =>
t.getRepository(Webhook).save({
url: webhookBaseUrl + webhookPath,
user: { id: user.id },
eventTypes: ['PAGE_CREATED'],
}),
undefined,
webhook = await createWebhook(
{
url: webhookBaseUrl + webhookPath,
user: { id: user.id },
eventTypes: ['PAGE_CREATED'],
},
user.id
)
})
after(async () => {
// clean up
await deleteTestUser(user.id)
await deleteUser(user.id)
})
describe('trigger webhooks', () => {

View file

@ -5,10 +5,10 @@ import { LibraryItem } from '../../src/entity/library_item'
import { ContentDisplayReport } from '../../src/entity/reports/content_display_report'
import { User } from '../../src/entity/user'
import { ReportType } from '../../src/generated/graphql'
import { authTrx, getRepository } from '../../src/repository'
import { getRepository } from '../../src/repository'
import { saveContentDisplayReport } from '../../src/services/reports'
import { createTestUser, deleteTestUser } from '../db'
import { createTestLibraryItem } from '../util'
import { deleteUser } from '../../src/services/user'
import { createTestLibraryItem, createTestUser } from '../db'
chai.use(sinonChai)
@ -22,7 +22,7 @@ describe('saveContentDisplayReport', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
it('creates a report', async () => {

View file

@ -5,7 +5,8 @@ import sinon from 'sinon'
import sinonChai from 'sinon-chai'
import { StatusType, User } from '../../src/entity/user'
import { getRepository } from '../../src/repository'
import { createGroup } from '../../src/services/groups'
import { findProfile } from '../../src/services/profile'
import { deleteUser } from '../../src/services/user'
import * as util from '../../src/utils/sendEmail'
import {
createTestUser,
@ -75,7 +76,7 @@ describe('create user', () => {
const user = await getRepository(User).findOneBy({
name: 'userWithoutProfile',
})
await deleteTestUser(user!.id)
await deleteUser(user!.id)
})
const name = 'userWithoutProfile'
@ -83,7 +84,7 @@ describe('create user', () => {
await createTestUser(user.name)
const profile = await getProfile(user)
const profile = await findProfile(user)
expect(profile).to.exist
})
@ -101,7 +102,7 @@ describe('create user', () => {
afterEach(async () => {
sinon.restore()
const user = await getRepository(User).findOneBy({ name })
await deleteTestUser(user!.id)
await deleteUser(user!.id)
})
it('creates the user with pending status and correct name', async () => {
@ -126,7 +127,7 @@ describe('create user', () => {
after(async () => {
sinon.restore()
const user = await getRepository(User).findOneBy({ name })
await deleteTestUser(user!.id)
await deleteUser(user!.id)
})
it('rejects with error', async () => {

View file

@ -3,10 +3,11 @@ import 'mocha'
import nock from 'nock'
import { ReceivedEmail } from '../../src/entity/received_email'
import { User } from '../../src/entity/user'
import { authTrx } from '../../src/repository'
import { findLibraryItemByUrl } from '../../src/services/library_item'
import { saveReceivedEmail } from '../../src/services/received_emails'
import { saveEmail } from '../../src/services/save_email'
import { createTestUser, deleteTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
describe('saveEmail', () => {
const fakeContent = 'fake content'
@ -22,23 +23,19 @@ describe('saveEmail', () => {
.reply(200)
.persist()
receivedEmail = await authTrx(
(t) =>
t.getRepository(ReceivedEmail).save({
user: { id: user.id },
from: '',
to: '',
subject: '',
html: '',
type: 'non-article',
}),
undefined,
user.id
receivedEmail = await saveReceivedEmail(
'',
'',
'',
'',
'',
user.id,
'non-article'
)
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
scope.persist(false)
})

View file

@ -5,11 +5,13 @@ import { NewsletterEmail } from '../../src/entity/newsletter_email'
import { ReceivedEmail } from '../../src/entity/received_email'
import { Subscription } from '../../src/entity/subscription'
import { User } from '../../src/entity/user'
import { authTrx, getRepository } from '../../src/repository'
import { getRepository } from '../../src/repository'
import { findLibraryItemByUrl } from '../../src/services/library_item'
import { createNewsletterEmail } from '../../src/services/newsletters'
import { saveReceivedEmail } from '../../src/services/received_emails'
import { saveNewsletter } from '../../src/services/save_newsletter_email'
import { createTestUser, deleteTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
describe('saveNewsletterEmail', () => {
const fakeContent = 'fake content'
@ -25,24 +27,19 @@ describe('saveNewsletterEmail', () => {
before(async () => {
user = await createTestUser('fakeUser')
newsletterEmail = await createNewsletterEmail(user.id)
receivedEmail = await authTrx(
(t) =>
t.getRepository(ReceivedEmail).save({
user: { id: user.id },
from,
to: newsletterEmail.address,
subject: title,
text,
html: '',
type: 'non-article',
}),
undefined,
user.id
receivedEmail = await saveReceivedEmail(
from,
newsletterEmail.address,
title,
text,
'',
user.id,
'non-article'
)
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
it('adds the newsletter to the library', async () => {

View file

@ -1,10 +1,6 @@
import supertest from 'supertest'
import { DeepPartial } from 'typeorm'
import { v4 } from 'uuid'
import { Label } from '../src/entity/label'
import { LibraryItem } from '../src/entity/library_item'
import { createApp } from '../src/server'
import { createLibraryItem } from '../src/services/library_item'
import { corsConfig } from '../src/utils/corsConfig'
const { app, apollo } = createApp()
@ -36,19 +32,3 @@ export const graphqlRequest = (
export const generateFakeUuid = () => {
return v4()
}
export const createTestLibraryItem = async (
userId: string,
labels?: Label[]
): Promise<LibraryItem> => {
const item: DeepPartial<LibraryItem> = {
user: { id: userId },
title: 'test title',
originalContent: '<p>test content</p>',
originalUrl: 'https://blog.omnivore.app/test-url',
slug: 'test-with-omnivore',
labels,
}
return createLibraryItem(item, userId)
}

View file

@ -12,7 +12,8 @@ import {
import nock from 'nock'
import chaiAsPromised from 'chai-as-promised'
import { User } from '../../src/entity/user'
import { createTestUser, deleteTestUser } from '../db'
import { createTestUser } from '../db'
import { deleteUser } from '../../src/services/user'
chai.use(chaiAsPromised)
@ -112,7 +113,7 @@ describe('isProbablyArticle', () => {
})
after(async () => {
await deleteTestUser(user.id)
await deleteUser(user.id)
})
it('returns true when email is signed up with us', async () => {