Merge pull request #2891 from omnivore-app/disable-database-query-log-in-github-action

disable database query logs in github action
This commit is contained in:
Hongbo Wu 2023-10-10 10:42:18 +08:00 committed by GitHub
commit fe3093834c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 199 additions and 256 deletions

View file

@ -27,21 +27,6 @@ jobs:
--health-retries 5
ports:
- 5432
elastic:
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.1
env:
discovery.type: single-node
http.cors.allow-origin: '*'
http.cors.enabled: true
http.cors.allow-headers: 'X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization'
http.cors.allow-credentials: true
options: >-
--health-cmd "curl http://0.0.0.0:9200/_cluster/health"
--health-interval 10s
--health-timeout 5s
--health-retries 10
ports:
- 9200
redis:
image: redis
options: >-
@ -82,22 +67,12 @@ jobs:
PG_USER: postgres
PG_PASSWORD: postgres
PG_DB: omnivore_test
ELASTIC_URL: http://localhost:${{ job.services.elastic.ports[9200] }}/
PGPASSWORD: postgres # This is required for the psql command to work without a password prompt
- name: TypeScript Build and Lint
run: |
source ~/.nvm/nvm.sh
yarn build
yarn lint
env:
PG_HOST: localhost
PG_PORT: ${{ job.services.postgres.ports[5432] }}
PG_USER: app_user
PG_PASSWORD: app_pass
PG_DB: omnivore_test
PG_POOL_MAX: 10
ELASTIC_URL: http://localhost:${{ job.services.elastic.ports[9200] }}/
REDIS_URL: redis://localhost:${{ job.services.redis.ports[6379] }}
- name: Tests
run: |
source ~/.nvm/nvm.sh
@ -108,8 +83,7 @@ jobs:
PG_USER: app_user
PG_PASSWORD: app_pass
PG_DB: omnivore_test
PG_POOL_MAX: 10
ELASTIC_URL: http://localhost:${{ job.services.elastic.ports[9200] }}/
PG_LOGGER: debug
REDIS_URL: redis://localhost:${{ job.services.redis.ports[6379] }}
build-docker-images:
name: Build docker images

View file

@ -13,10 +13,10 @@ import * as httpContext from 'express-http-context2'
import * as jwt from 'jsonwebtoken'
import { EntityManager } from 'typeorm'
import { promisify } from 'util'
import { appDataSource } from './data_source'
import { sanitizeDirectiveTransformer } from './directives'
import { env } from './env'
import { createPubSubClient } from './pubsub'
import { entityManager } from './repository'
import { functionResolvers } from './resolvers/function_resolvers'
import { ClaimsToSet, ResolverContext } from './resolvers/types'
import ScalarResolvers from './scalars'
@ -79,7 +79,7 @@ const contextFunc: ContextFunction<ExpressContext, ResolverContext> = async ({
cb: (em: EntityManager) => TResult,
userRole?: string
): Promise<TResult> =>
entityManager.transaction(async (tx) => {
appDataSource.transaction(async (tx) => {
await setClaims(tx, undefined, userRole)
return cb(tx)
}),

View file

@ -1,37 +0,0 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { PubSub } from '@google-cloud/pubsub'
import {
BaseEntity,
EntitySubscriberInterface,
EventSubscriber,
InsertEvent,
} from 'typeorm'
import { env } from '../env'
import { logger } from '../utils/logger'
const TOPIC_NAME = 'EntityCreated'
@EventSubscriber()
export class PublishEntitySubscriber implements EntitySubscriberInterface {
async afterInsert(event: InsertEvent<BaseEntity>): Promise<void> {
const client = new PubSub()
const msg = JSON.stringify({
type: 'EntityCreated',
entity: event.entity,
entityClass: event.entity?.constructor?.name,
})
if (env.dev.isLocal) {
logger.info('PublishEntitySubscriber', msg)
return
}
await client
.topic(TOPIC_NAME)
.publishMessage({ data: Buffer.from(msg) })
.catch((err) => {
logger.error('PublishEntitySubscriber error publishing event', err)
})
}
}

View file

@ -0,0 +1,34 @@
import {
EntitySubscriberInterface,
EventSubscriber,
InsertEvent,
} from 'typeorm'
import { Profile } from '../../entity/profile'
import { createDefaultFiltersForUser } from '../../services/create_user'
import { addPopularReadsForNewUser } from '../../services/popular_reads'
@EventSubscriber()
export class AddPopularReadsToNewUser
implements EntitySubscriberInterface<Profile>
{
listenTo() {
return Profile
}
async afterInsert(event: InsertEvent<Profile>): Promise<void> {
await addPopularReadsForNewUser(event.entity.user.id, event.manager)
}
}
@EventSubscriber()
export class AddDefaultFiltersToNewUser
implements EntitySubscriberInterface<Profile>
{
listenTo() {
return Profile
}
async afterInsert(event: InsertEvent<Profile>): Promise<void> {
await createDefaultFiltersForUser(event.manager)(event.entity.user.id)
}
}

View file

@ -1,64 +0,0 @@
import {
EntitySubscriberInterface,
EventSubscriber,
InsertEvent,
} from 'typeorm'
import { Profile } from '../../entity/profile'
import { createPubSubClient } from '../../pubsub'
import { addPopularReadsForNewUser } from '../../services/popular_reads'
import { IntercomClient } from '../../utils/intercom'
@EventSubscriber()
export class CreateIntercomAccount
implements EntitySubscriberInterface<Profile>
{
listenTo() {
return Profile
}
async afterInsert(event: InsertEvent<Profile>): Promise<void> {
const profile = event.entity
const customAttributes: { source_user_id: string } = {
source_user_id: profile.user.sourceUserId,
}
await IntercomClient?.contacts.createUser({
email: profile.user.email,
externalId: profile.user.id,
name: profile.user.name,
avatar: profile.pictureUrl || undefined,
customAttributes: customAttributes,
signedUpAt: Math.floor(Date.now() / 1000),
})
}
}
@EventSubscriber()
export class PublishNewUserEvent implements EntitySubscriberInterface<Profile> {
listenTo() {
return Profile
}
async afterInsert(event: InsertEvent<Profile>): Promise<void> {
const client = createPubSubClient()
await client.userCreated(
event.entity.user.id,
event.entity.user.email,
event.entity.user.name,
event.entity.username
)
}
}
@EventSubscriber()
export class AddPopularReadsToNewUser
implements EntitySubscriberInterface<Profile>
{
listenTo() {
return Profile
}
async afterInsert(event: InsertEvent<Profile>): Promise<void> {
await addPopularReadsForNewUser(event.entity.user.id, event.manager)
}
}

View file

@ -1,6 +1,6 @@
import { DeepPartial } from 'typeorm'
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'
import { entityManager } from '.'
import { appDataSource } from '../data_source'
import { Highlight } from '../entity/highlight'
import { unescapeHtml } from '../utils/helpers'
@ -16,7 +16,7 @@ const unescapeHighlight = (highlight: DeepPartial<Highlight>) => {
return highlight
}
export const highlightRepository = entityManager
export const highlightRepository = appDataSource
.getRepository(Highlight)
.extend({
findById(id: string) {

View file

@ -22,7 +22,7 @@ export const setClaims = async (
export const authTrx = async <T>(
fn: (manager: EntityManager) => Promise<T>,
em = entityManager,
em = appDataSource.manager,
uid?: string,
userRole?: string
): Promise<T> => {
@ -40,7 +40,5 @@ export const authTrx = async <T>(
}
export const getRepository = <T>(entity: EntityTarget<T>) => {
return entityManager.getRepository(entity)
return appDataSource.getRepository(entity)
}
export const entityManager = appDataSource.manager

View file

@ -1,6 +1,6 @@
import { In } from 'typeorm'
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'
import { entityManager } from '.'
import { appDataSource } from '../data_source'
import { Label } from '../entity/label'
import { generateRandomColor } from '../utils/helpers'
@ -38,7 +38,7 @@ const convertToLabel = (label: CreateLabelInput, userId: string) => {
}
}
export const labelRepository = entityManager.getRepository(Label).extend({
export const labelRepository = appDataSource.getRepository(Label).extend({
findById(id: string) {
return this.findOneBy({ id })
},

View file

@ -1,7 +1,7 @@
import { entityManager } from '.'
import { appDataSource } from '../data_source'
import { LibraryItem } from '../entity/library_item'
export const libraryItemRepository = entityManager
export const libraryItemRepository = appDataSource
.getRepository(LibraryItem)
.extend({
findById(id: string) {

View file

@ -1,5 +1,5 @@
import { In } from 'typeorm'
import { entityManager } from '.'
import { appDataSource } from '../data_source'
import { User } from './../entity/user'
const TOP_USERS = [
@ -14,7 +14,7 @@ const TOP_USERS = [
]
export const MAX_RECORDS_LIMIT = 1000
export const userRepository = entityManager.getRepository(User).extend({
export const userRepository = appDataSource.getRepository(User).extend({
findById(id: string) {
return this.findOneBy({ id })
},

View file

@ -1,29 +1,22 @@
import { EntityManager } from 'typeorm'
import { appDataSource } from '../data_source'
import { Filter } from '../entity/filter'
import { GroupMembership } from '../entity/groups/group_membership'
import { Invite } from '../entity/groups/invite'
import { Profile } from '../entity/profile'
import { StatusType, User } from '../entity/user'
import { env } from '../env'
import { SignupErrorCode } from '../generated/graphql'
import { authTrx, entityManager, getRepository } from '../repository'
import { createPubSubClient } from '../pubsub'
import { authTrx, getRepository } from '../repository'
import { userRepository } from '../repository/user'
import { AuthProvider } from '../routers/auth/auth_types'
import { analytics } from '../utils/analytics'
import { IntercomClient } from '../utils/intercom'
import { logger } from '../utils/logger'
import { validateUsername } from '../utils/usernamePolicy'
import { sendConfirmationEmail } from './send_emails'
import { Filter } from '../entity/filter'
import { analytics } from '../utils/analytics'
import { env } from '../env'
const TOP_USERS = [
'jacksonh',
'nat',
'luis',
'satindar',
'malandrina',
'patrick',
'alexgutjahr',
'hongbowu',
]
export const MAX_RECORDS_LIMIT = 1000
export const createUser = async (input: {
@ -71,7 +64,7 @@ export const createUser = async (input: {
return Promise.reject({ errorCode: SignupErrorCode.InvalidUsername })
}
const [user, profile] = await entityManager.transaction<[User, Profile]>(
const [user, profile] = await appDataSource.transaction<[User, Profile]>(
async (t) => {
let hasInvite = false
let invite: Invite | null = null
@ -110,17 +103,29 @@ export const createUser = async (input: {
})
}
await createDefaultFiltersForUser(t)(user.id)
return [user, profile]
}
)
if (input.pendingConfirmation) {
if (!(await sendConfirmationEmail(user))) {
return Promise.reject({ errorCode: SignupErrorCode.InvalidEmail })
}
const customAttributes: { source_user_id: string } = {
source_user_id: user.sourceUserId,
}
await IntercomClient?.contacts.createUser({
email: user.email,
externalId: user.id,
name: user.name,
avatar: profile.pictureUrl || undefined,
customAttributes: customAttributes,
signedUpAt: Math.floor(Date.now() / 1000),
})
const pubsubClient = createPubSubClient()
await pubsubClient.userCreated(
user.id,
user.email,
user.name,
profile.username
)
analytics.track({
userId: user.id,
@ -132,10 +137,16 @@ export const createUser = async (input: {
},
})
if (input.pendingConfirmation) {
if (!(await sendConfirmationEmail(user))) {
return Promise.reject({ errorCode: SignupErrorCode.InvalidEmail })
}
}
return [user, profile]
}
const createDefaultFiltersForUser =
export const createDefaultFiltersForUser =
(t: EntityManager) =>
async (userId: string): Promise<Filter[]> => {
const defaultFilters = [

View file

@ -1,8 +1,9 @@
import * as jwt from 'jsonwebtoken'
import { DeepPartial, FindOptionsWhere, IsNull, Not } from 'typeorm'
import { appDataSource } from '../data_source'
import { Feature } from '../entity/feature'
import { env } from '../env'
import { entityManager, getRepository } from '../repository'
import { getRepository } from '../repository'
import { logger } from '../utils/logger'
export enum FeatureName {
@ -41,7 +42,7 @@ const optInUltraRealisticVoice = async (uid: string): Promise<Feature> => {
const MAX_USERS = 1500
// opt in to feature for the first 1500 users
const optedInFeatures = (await entityManager.query(
const optedInFeatures = (await appDataSource.query(
`insert into omnivore.features (user_id, name, granted_at)
select $1, $2, $3 from omnivore.features
where name = $2 and granted_at is not null

View file

@ -1,4 +1,5 @@
import { nanoid } from 'nanoid'
import { appDataSource } from '../data_source'
import { Group } from '../entity/groups/group'
import { GroupMembership } from '../entity/groups/group_membership'
import { Invite } from '../entity/groups/invite'
@ -6,7 +7,7 @@ import { RuleActionType } from '../entity/rule'
import { User } from '../entity/user'
import { homePageURL } from '../env'
import { RecommendationGroup, User as GraphqlUser } from '../generated/graphql'
import { entityManager, getRepository } from '../repository'
import { getRepository } from '../repository'
import { userDataToUser } from '../utils/helpers'
import { findOrCreateLabels } from './labels'
import { createRule } from './rules'
@ -21,7 +22,7 @@ export const createGroup = async (input: {
onlyAdminCanPost?: boolean | null
onlyAdminCanSeeMembers?: boolean | null
}): Promise<[Group, Invite]> => {
const [group, invite] = await entityManager.transaction<[Group, Invite]>(
const [group, invite] = await appDataSource.transaction<[Group, Invite]>(
async (t) => {
// Max number of groups a user can create
const maxGroups = 3
@ -113,7 +114,7 @@ export const joinGroup = async (
user: User,
inviteCode: string
): Promise<RecommendationGroup> => {
const invite = await entityManager.transaction<Invite>(async (t) => {
const invite = await appDataSource.transaction<Invite>(async (t) => {
// Check if the invite exists
const invite = await t
.getRepository(Invite)
@ -173,7 +174,7 @@ export const leaveGroup = async (
user: User,
groupId: string
): Promise<boolean> => {
return entityManager.transaction(async (t) => {
return appDataSource.transaction(async (t) => {
const group = await t
.getRepository(Group)
.createQueryBuilder('group')

View file

@ -2,9 +2,10 @@ import * as httpContext from 'express-http-context2'
import { readFileSync } from 'fs'
import path from 'path'
import { DeepPartial, EntityManager } from 'typeorm'
import { appDataSource } from '../data_source'
import { LibraryItem } from '../entity/library_item'
import { PageType } from '../generated/graphql'
import { authTrx, entityManager } from '../repository'
import { authTrx } from '../repository'
import { libraryItemRepository } from '../repository/library_item'
import { generateSlug, stringToHash, wordsCount } from '../utils/helpers'
import { logger } from '../utils/logger'
@ -107,7 +108,7 @@ const addPopularReads = async (
export const addPopularReadsForNewUser = async (
userId: string,
em = entityManager
em = appDataSource.manager
): Promise<void> => {
const defaultReads = ['omnivore_organize', 'power_read_it_later']

View file

@ -1,8 +1,10 @@
import { AbuseReport } from '../entity/reports/abuse_report'
import { ContentDisplayReport } from '../entity/reports/content_display_report'
import { env } from '../env'
import { ReportItemInput, ReportType } from '../generated/graphql'
import { authTrx, getRepository } from '../repository'
import { logger } from '../utils/logger'
import { sendEmail } from '../utils/sendEmail'
import { findLibraryItemById } from './library_item'
export const saveContentDisplayReport = async (
@ -18,7 +20,7 @@ export const saveContentDisplayReport = async (
// We capture the article content and original html now, in case it
// reparsed or updated later, this gives us a view of exactly
// what the user saw.
const result = await getRepository(ContentDisplayReport).save({
const report = await getRepository(ContentDisplayReport).save({
user: { id: uid },
content: item.readableContent,
originalHtml: item.originalContent || undefined,
@ -27,7 +29,23 @@ export const saveContentDisplayReport = async (
libraryItemId: item.id,
})
return !!result
const message = `A new content display report was created by:
${report.user.id} for URL: ${report.originalUrl}
${report.reportComment}`
logger.info(message)
if (!env.dev.isLocal) {
// If we are in the local environment, just log a message, otherwise email the report
await sendEmail({
to: env.sender.feedback,
subject: 'New content display report',
text: message,
from: env.sender.message,
})
}
return !!report
}
export const saveAbuseReport = async (

View file

@ -1,8 +1,9 @@
import axios from 'axios'
import { appDataSource } from '../data_source'
import { NewsletterEmail } from '../entity/newsletter_email'
import { Subscription } from '../entity/subscription'
import { SubscriptionStatus, SubscriptionType } from '../generated/graphql'
import { authTrx, entityManager, getRepository } from '../repository'
import { authTrx, getRepository } from '../repository'
import { logger } from '../utils/logger'
import { sendEmail } from '../utils/sendEmail'
@ -105,7 +106,7 @@ export const saveSubscription = async ({
}
const existingSubscription = await getSubscriptionByName(name, userId)
const result = await entityManager.transaction(async (tx) => {
const result = await appDataSource.transaction(async (tx) => {
if (existingSubscription) {
// update subscription if already exists
await tx

View file

@ -74,11 +74,6 @@ interface BackendEnv {
gcsUploadSAKeyFilePath: string
gcsUploadPrivateBucket: string
}
elastic: {
url: string
username: string
password: string
}
sender: {
message: string
feedback: string
@ -144,8 +139,6 @@ const nullableEnvVars = [
'GAUTH_SECRET',
'SEGMENT_WRITE_KEY',
'TWITTER_BEARER_TOKEN',
'ELASTIC_USERNAME',
'ELASTIC_PASSWORD',
'GCS_UPLOAD_PRIVATE_BUCKET',
'SENDER_MESSAGE',
'SENDER_FEEDBACK',
@ -267,11 +260,6 @@ export function getEnv(): BackendEnv {
gcsUploadSAKeyFilePath: parse('GCS_UPLOAD_SA_KEY_FILE_PATH'),
gcsUploadPrivateBucket: parse('GCS_UPLOAD_PRIVATE_BUCKET'),
}
const elastic = {
url: parse('ELASTIC_URL'),
username: parse('ELASTIC_USERNAME'),
password: parse('ELASTIC_PASSWORD'),
}
const sender = {
message: parse('SENDER_MESSAGE'),
feedback: parse('SENDER_FEEDBACK'),
@ -317,7 +305,6 @@ export function getEnv(): BackendEnv {
dev,
fileUpload,
queue,
elastic,
sender,
sendgrid,
readwise,

View file

@ -260,15 +260,17 @@ export const enqueueParseRequest = async ({
// If there is no Google Cloud Project Id exposed, it means that we are in local environment
if (env.dev.isLocal || !GOOGLE_CLOUD_PROJECT) {
// Calling the handler function directly.
setTimeout(() => {
axios.post(env.queue.contentFetchUrl, payload).catch((error) => {
logError(error)
logger.error(
`Error occurred while requesting local puppeteer-parse function\nPlease, ensure your function is set up properly and running using "yarn start" from the "/pkg/gcf/puppeteer-parse" folder`
)
})
}, 0)
if (env.queue.contentFetchUrl) {
// Calling the handler function directly.
setTimeout(() => {
axios.post(env.queue.contentFetchUrl, payload).catch((error) => {
logError(error)
logger.error(
`Error occurred while requesting local puppeteer-parse function\nPlease, ensure your function is set up properly and running using "yarn start" from the "/pkg/gcf/puppeteer-parse" folder`
)
})
}, 0)
}
return ''
}
@ -414,12 +416,14 @@ export const enqueueTextToSpeech = async ({
const taskHandlerUrl = `${env.queue.textToSpeechTaskHandlerUrl}?token=${token}`
// If there is no Google Cloud Project Id exposed, it means that we are in local environment
if (env.dev.isLocal || !GOOGLE_CLOUD_PROJECT) {
// Calling the handler function directly.
setTimeout(() => {
axios.post(taskHandlerUrl, payload).catch((error) => {
logError(error)
})
}, 0)
if (env.queue.textToSpeechTaskHandlerUrl) {
// Calling the handler function directly.
setTimeout(() => {
axios.post(taskHandlerUrl, payload).catch((error) => {
logError(error)
})
}, 0)
}
return ''
}
const createdTasks = await createHttpTaskWithToken({
@ -461,16 +465,18 @@ export const enqueueRecommendation = async (
}
// If there is no Google Cloud Project Id exposed, it means that we are in local environment
if (env.dev.isLocal || !GOOGLE_CLOUD_PROJECT) {
// Calling the handler function directly.
setTimeout(() => {
axios
.post(env.queue.recommendationTaskHandlerUrl, payload, {
headers,
})
.catch((error) => {
logError(error)
})
}, 0)
if (env.queue.recommendationTaskHandlerUrl) {
// Calling the handler function directly.
setTimeout(() => {
axios
.post(env.queue.recommendationTaskHandlerUrl, payload, {
headers,
})
.catch((error) => {
logError(error)
})
}, 0)
}
return ''
}
@ -505,16 +511,18 @@ export const enqueueImportFromIntegration = async (
}
// If there is no Google Cloud Project Id exposed, it means that we are in local environment
if (env.dev.isLocal || !GOOGLE_CLOUD_PROJECT) {
// Calling the handler function directly.
setTimeout(() => {
axios
.post(`${env.queue.integrationTaskHandlerUrl}/import`, payload, {
headers,
})
.catch((error) => {
logError(error)
})
}, 0)
if (env.queue.integrationTaskHandlerUrl) {
// Calling the handler function directly.
setTimeout(() => {
axios
.post(`${env.queue.integrationTaskHandlerUrl}/import`, payload, {
headers,
})
.catch((error) => {
logError(error)
})
}, 0)
}
return nanoid()
}
@ -552,16 +560,18 @@ export const enqueueThumbnailTask = async (
// If there is no Google Cloud Project Id exposed, it means that we are in local environment
if (env.dev.isLocal || !GOOGLE_CLOUD_PROJECT) {
// Calling the handler function directly.
setTimeout(() => {
axios
.post(env.queue.thumbnailTaskHandlerUrl, payload, {
headers,
})
.catch((error) => {
logError(error)
})
}, 0)
if (env.queue.thumbnailTaskHandlerUrl) {
// Calling the handler function directly.
setTimeout(() => {
axios
.post(env.queue.thumbnailTaskHandlerUrl, payload, {
headers,
})
.catch((error) => {
logError(error)
})
}, 0)
}
return ''
}
@ -599,16 +609,18 @@ export const enqueueRssFeedFetch = async (
// If there is no Google Cloud Project Id exposed, it means that we are in local environment
if (env.dev.isLocal || !GOOGLE_CLOUD_PROJECT) {
// Calling the handler function directly.
setTimeout(() => {
axios
.post(env.queue.rssFeedTaskHandlerUrl, payload, {
headers,
})
.catch((error) => {
logError(error)
})
}, 0)
if (env.queue.rssFeedTaskHandlerUrl) {
// Calling the handler function directly.
setTimeout(() => {
axios
.post(env.queue.rssFeedTaskHandlerUrl, payload, {
headers,
})
.catch((error) => {
logError(error)
})
}, 0)
}
return nanoid()
}

View file

@ -401,7 +401,7 @@ const getJSONLdLinkMetadata = async (
return result
} catch (error) {
logger.error(`Unable to get JSONLD link of the article`, error)
logger.error('Unable to get JSONLD link of the article')
return result
}
}

View file

@ -26,7 +26,7 @@ export const sendEmail = async (msg: MailDataRequired): Promise<boolean> => {
const client = new MailService()
if (!process.env.SENDGRID_MSGS_API_KEY) {
if (env.dev.isLocal) {
logger.error('SendGrid API key not set.\nSending email:', msg)
logger.info('SendGrid API key not set.\nSending email:', msg)
return true
}

View file

@ -1,5 +1,4 @@
import { DeepPartial } from 'typeorm'
import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
import { appDataSource } from '../src/data_source'
import { Filter } from '../src/entity/filter'
import { Label } from '../src/entity/label'
@ -7,7 +6,7 @@ import { LibraryItem } from '../src/entity/library_item'
import { Reminder } from '../src/entity/reminder'
import { User } from '../src/entity/user'
import { UserDeviceToken } from '../src/entity/user_device_tokens'
import { entityManager, getRepository, setClaims } from '../src/repository'
import { getRepository, setClaims } from '../src/repository'
import { userRepository } from '../src/repository/user'
import { createUser } from '../src/services/create_user'
import { saveLabelsInLibraryItem } from '../src/services/labels'
@ -27,13 +26,18 @@ export const createTestConnection = async (): Promise<void> => {
logging: ['query', 'info'],
entities: [__dirname + '/../src/entity/**/*{.js,.ts}'],
subscribers: [__dirname + '/../src/events/**/*{.js,.ts}'],
namingStrategy: new SnakeNamingStrategy(),
logger: process.env.PG_LOGGER as
| 'advanced-console'
| 'simple-console'
| 'file'
| 'debug'
| undefined,
})
await appDataSource.initialize()
}
export const deleteFiltersFromUser = async (userId: string) => {
await entityManager.transaction(async (t) => {
await appDataSource.transaction(async (t) => {
await setClaims(t, userId)
const filterRepo = t.getRepository(Filter)

View file

@ -80,7 +80,7 @@ describe('Webhooks API', () => {
}
`
const res = await graphqlRequest(query, authToken)
const res = await graphqlRequest(query, authToken).expect(200)
expect(res.body.data.webhook.webhook.id).to.eql(webhook.id)
expect(res.body.data.webhook.webhook.url).to.eql(webhook.url)
@ -108,7 +108,7 @@ describe('Webhooks API', () => {
}
`
const res = await graphqlRequest(query, authToken)
const res = await graphqlRequest(query, authToken).expect(200)
const webhooks = await findWebhooks(user.id)
expect(res.body.data.webhooks.webhooks).to.eql(
@ -165,7 +165,7 @@ describe('Webhooks API', () => {
})
it('should create a webhook', async () => {
const res = await graphqlRequest(query, authToken)
const res = await graphqlRequest(query, authToken).expect(200)
expect(res.body.data.setWebhook.webhook).to.be.an('object')
expect(res.body.data.setWebhook.webhook.url).to.eql(webhookUrl)
@ -195,7 +195,7 @@ describe('Webhooks API', () => {
})
it('should update a webhook', async () => {
const res = await graphqlRequest(query, authToken)
const res = await graphqlRequest(query, authToken).expect(200)
expect(res.body.data.setWebhook.webhook).to.be.an('object')
expect(res.body.data.setWebhook.webhook.url).to.eql(webhookUrl)
@ -240,7 +240,7 @@ describe('Webhooks API', () => {
})
it('should delete a webhook', async () => {
const res = await graphqlRequest(query, authToken)
const res = await graphqlRequest(query, authToken).expect(200)
const webhook = await findWebhookById(webhookId, user.id)
expect(res.body.data.deleteWebhook.webhook).to.be.an('object')

View file

@ -16,7 +16,9 @@ describe('/article/save API', () => {
// We need to mock the pupeeteer-parse
// service here because in dev mode the task gets
// called immediately.
nock(env.queue.contentFetchUrl).post('/').reply(200)
if (env.queue.contentFetchUrl) {
nock(env.queue.contentFetchUrl).post('/').reply(200)
}
before(async () => {
// create test user and login