mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Merge pull request #245 from omnivore-app/feature/add-label-to-newsletters
add Newsletter label to the page created by newsletters email
This commit is contained in:
commit
3b9e1d36ae
20 changed files with 213 additions and 167 deletions
|
|
@ -37,8 +37,11 @@ export const createPubSubClient = (): PubsubClient => {
|
|||
Buffer.from(JSON.stringify({ userId, email, name, username }))
|
||||
)
|
||||
},
|
||||
pageSaved: (page: Partial<Page>): Promise<void> => {
|
||||
return publish('pageSaved', Buffer.from(JSON.stringify(page)))
|
||||
pageSaved: (page: Partial<Page>, userId: string): Promise<void> => {
|
||||
return publish(
|
||||
'pageSaved',
|
||||
Buffer.from(JSON.stringify({ ...page, userId }))
|
||||
)
|
||||
},
|
||||
pageCreated: (page: Page): Promise<void> => {
|
||||
return publish('pageCreated', Buffer.from(JSON.stringify(page)))
|
||||
|
|
@ -70,7 +73,7 @@ export interface PubsubClient {
|
|||
username: string
|
||||
) => Promise<void>
|
||||
pageCreated: (page: Page) => Promise<void>
|
||||
pageSaved: (page: Partial<Page>) => Promise<void>
|
||||
pageSaved: (page: Partial<Page>, userId: string) => Promise<void>
|
||||
pageDeleted: (id: string, userId: string) => Promise<void>
|
||||
reportSubmitted(
|
||||
submitterId: string | undefined,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {
|
|||
} from './types'
|
||||
import { readFileSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
import { Label } from '../entity/label'
|
||||
|
||||
const INDEX_NAME = 'pages'
|
||||
const INDEX_ALIAS = 'pages_alias'
|
||||
|
|
@ -161,7 +162,11 @@ export const createPage = async (
|
|||
const { body } = await client.index({
|
||||
id: page.id || undefined,
|
||||
index: INDEX_ALIAS,
|
||||
body: page,
|
||||
body: {
|
||||
...page,
|
||||
updatedAt: new Date(),
|
||||
createdAt: new Date(),
|
||||
},
|
||||
refresh: ctx.refresh,
|
||||
})
|
||||
|
||||
|
|
@ -184,14 +189,17 @@ export const updatePage = async (
|
|||
index: INDEX_ALIAS,
|
||||
id,
|
||||
body: {
|
||||
doc: page,
|
||||
doc: {
|
||||
...page,
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
},
|
||||
refresh: ctx.refresh,
|
||||
})
|
||||
|
||||
if (body.result !== 'updated') return false
|
||||
|
||||
await ctx.pubsub.pageSaved(page)
|
||||
await ctx.pubsub.pageSaved(page, ctx.uid)
|
||||
|
||||
return true
|
||||
} catch (e) {
|
||||
|
|
@ -200,9 +208,40 @@ export const updatePage = async (
|
|||
}
|
||||
}
|
||||
|
||||
export const addLabelInPage = async (
|
||||
id: string,
|
||||
label: Label,
|
||||
ctx: PageContext
|
||||
): Promise<boolean> => {
|
||||
try {
|
||||
const { body } = await client.update({
|
||||
index: INDEX_ALIAS,
|
||||
id,
|
||||
body: {
|
||||
script: {
|
||||
source:
|
||||
'if (!ctx._source.labels.contains(params.label)) { ctx._source.labels.add(label) }',
|
||||
lang: 'painless',
|
||||
params: {
|
||||
label: label,
|
||||
},
|
||||
},
|
||||
doc: {
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
},
|
||||
refresh: ctx.refresh,
|
||||
})
|
||||
|
||||
return body.result === 'updated'
|
||||
} catch (e) {
|
||||
console.error('failed to update a page in elastic', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const deletePage = async (
|
||||
id: string,
|
||||
userId: string,
|
||||
ctx: PageContext
|
||||
): Promise<boolean> => {
|
||||
try {
|
||||
|
|
@ -214,7 +253,7 @@ export const deletePage = async (
|
|||
|
||||
if (body.deleted === 0) return false
|
||||
|
||||
await ctx.pubsub.pageDeleted(id, userId)
|
||||
await ctx.pubsub.pageDeleted(id, ctx.uid)
|
||||
|
||||
return true
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -151,4 +151,5 @@ export type ParamSet = PickTuple<Page, typeof keys>
|
|||
export interface PageContext {
|
||||
pubsub: PubsubClient
|
||||
refresh?: boolean
|
||||
uid: string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,13 +330,13 @@ export const createArticleResolver = authorized<
|
|||
existingPage.url = uploadFileUrlOverride || articleToSave.url
|
||||
existingPage.hash = articleToSave.hash
|
||||
|
||||
await updatePage(existingPage.id, existingPage, ctx)
|
||||
await updatePage(existingPage.id, existingPage, { ...ctx, uid })
|
||||
|
||||
log.info('page updated in elastic', existingPage.id)
|
||||
articleToSave = existingPage
|
||||
} else {
|
||||
// create new page in elastic
|
||||
const pageId = await createPage(articleToSave, ctx)
|
||||
const pageId = await createPage(articleToSave, { ...ctx, uid })
|
||||
|
||||
if (!pageId) {
|
||||
return articleSavingRequestError(
|
||||
|
|
@ -626,7 +626,7 @@ export const setBookmarkArticleResolver = authorized<
|
|||
return { errorCodes: [SetBookmarkArticleErrorCode.NotFound] }
|
||||
}
|
||||
|
||||
await deletePage(userArticleRemoved.id, uid, { pubsub })
|
||||
await deletePage(userArticleRemoved.id, { pubsub, uid })
|
||||
|
||||
const highlightsUnshared = await authTrx(async (tx) => {
|
||||
return models.highlight.unshareAllHighlights(articleID, uid, tx)
|
||||
|
|
@ -660,7 +660,7 @@ export const setBookmarkArticleResolver = authorized<
|
|||
userId: uid,
|
||||
slug: generateSlug(article.title),
|
||||
}
|
||||
await updatePage(articleID, userArticle, { pubsub })
|
||||
await updatePage(articleID, userArticle, { pubsub, uid })
|
||||
|
||||
log.info('Article bookmarked', {
|
||||
article: Object.assign({}, article, {
|
||||
|
|
@ -737,7 +737,7 @@ export const saveArticleReadingProgressResolver = authorized<
|
|||
: userArticleRecord.readingProgressAnchorIndex,
|
||||
})
|
||||
|
||||
shouldUpdate && (await updatePage(id, updatedArticle, { pubsub }))
|
||||
shouldUpdate && (await updatePage(id, updatedArticle, { pubsub, uid }))
|
||||
|
||||
return {
|
||||
updatedArticle: {
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ export const createLabelResolver = authorized<
|
|||
// Check if label already exists ignoring case of name
|
||||
const existingLabel = await getRepository(Label).findOne({
|
||||
where: {
|
||||
user,
|
||||
name: ILike(name),
|
||||
},
|
||||
})
|
||||
|
|
@ -161,7 +162,10 @@ export const deleteLabelResolver = authorized<
|
|||
}
|
||||
|
||||
// delete label in elastic pages
|
||||
await deleteLabelInPages(uid, label.name, { pubsub: createPubSubClient() })
|
||||
await deleteLabelInPages(uid, label.name, {
|
||||
pubsub: createPubSubClient(),
|
||||
uid,
|
||||
})
|
||||
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
|
|
@ -225,7 +229,7 @@ export const setLabelsResolver = authorized<
|
|||
{
|
||||
labels,
|
||||
},
|
||||
{ pubsub }
|
||||
{ pubsub, uid }
|
||||
)
|
||||
|
||||
analytics.track({
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ export const setLinkArchivedResolver = authorized<
|
|||
{
|
||||
archivedAt: args.input.archived ? new Date() : null,
|
||||
},
|
||||
{ pubsub }
|
||||
{ pubsub, uid: claims.uid }
|
||||
)
|
||||
} catch (e) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export const savePageResolver = authorized<
|
|||
}
|
||||
|
||||
return savePage(
|
||||
ctx,
|
||||
{ ...ctx, uid },
|
||||
{ userId: user.id, username: user.profile.username },
|
||||
input
|
||||
)
|
||||
|
|
@ -70,5 +70,5 @@ export const saveFileResolver = authorized<
|
|||
return { errorCodes: [SaveErrorCode.Unauthorized] }
|
||||
}
|
||||
|
||||
return (await saveFile(ctx, user, input)) as SaveSuccess
|
||||
return (await saveFile({ ...ctx, uid }, user, input)) as SaveSuccess
|
||||
})
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ export function contentServiceRouter() {
|
|||
|
||||
const result = await updatePage(page.id, pageToUpdate, {
|
||||
pubsub: createPubSubClient(),
|
||||
uid: page.userId,
|
||||
})
|
||||
console.log(
|
||||
'Updating article text',
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ export function pdfAttachmentsRouter() {
|
|||
|
||||
const pageId = await createPage(articleToSave, {
|
||||
pubsub: createPubSubClient(),
|
||||
uid: user.id,
|
||||
})
|
||||
|
||||
res.send({ id: pageId })
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import DataLoader from 'dataloader'
|
||||
import { Label } from '../entity/label'
|
||||
import { getRepository, In } from 'typeorm'
|
||||
import { getRepository, ILike, In } from 'typeorm'
|
||||
import { Link } from '../entity/link'
|
||||
import { PageContext } from '../elastic/types'
|
||||
import { User } from '../entity/user'
|
||||
import { addLabelInPage } from '../elastic'
|
||||
|
||||
const batchGetLabelsFromLinkIds = async (
|
||||
linkIds: readonly string[]
|
||||
|
|
@ -17,3 +20,35 @@ const batchGetLabelsFromLinkIds = async (
|
|||
}
|
||||
|
||||
export const labelsLoader = new DataLoader(batchGetLabelsFromLinkIds)
|
||||
|
||||
export const addLabelToPage = async (
|
||||
ctx: PageContext,
|
||||
pageId: string,
|
||||
label: {
|
||||
name: string
|
||||
color: string
|
||||
description?: string
|
||||
}
|
||||
): Promise<boolean> => {
|
||||
const user = await getRepository(User).findOne(ctx.uid)
|
||||
|
||||
let labelEntity = await getRepository(Label).findOne({
|
||||
where: {
|
||||
user: user,
|
||||
name: ILike(label.name),
|
||||
},
|
||||
})
|
||||
|
||||
if (!labelEntity) {
|
||||
console.log('creating new label', label.name)
|
||||
|
||||
labelEntity = await getRepository(Label).save({
|
||||
...label,
|
||||
user,
|
||||
})
|
||||
}
|
||||
|
||||
console.log('adding label to page', label.name, pageId)
|
||||
|
||||
return addLabelInPage(pageId, labelEntity, ctx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { PubsubClient } from '../datalayer/pubsub'
|
||||
import { DataModels } from '../resolvers/types'
|
||||
import { generateSlug, stringToHash, validatedDate } from '../utils/helpers'
|
||||
import {
|
||||
parseOriginalContent,
|
||||
|
|
@ -7,13 +5,13 @@ import {
|
|||
parseUrlMetadata,
|
||||
} from '../utils/parser'
|
||||
import normalizeUrl from 'normalize-url'
|
||||
import { kx } from '../datalayer/knex_config'
|
||||
import { UserArticleData } from '../datalayer/links/model'
|
||||
import { setClaims } from '../datalayer/helpers'
|
||||
import { PubsubClient } from '../datalayer/pubsub'
|
||||
import { Page } from '../elastic/types'
|
||||
import { createPage, getPageByParam, updatePage } from '../elastic'
|
||||
|
||||
export type SaveContext = {
|
||||
pubsub: PubsubClient
|
||||
models: DataModels
|
||||
uid: string
|
||||
}
|
||||
|
||||
export type SaveEmailInput = {
|
||||
|
|
@ -25,9 +23,8 @@ export type SaveEmailInput = {
|
|||
|
||||
export const saveEmail = async (
|
||||
ctx: SaveContext,
|
||||
saverId: string,
|
||||
input: SaveEmailInput
|
||||
): Promise<UserArticleData | undefined> => {
|
||||
): Promise<Page | undefined> => {
|
||||
const url = input.url
|
||||
const parseResult = await parsePreparedContent(
|
||||
url,
|
||||
|
|
@ -47,7 +44,9 @@ export const saveEmail = async (
|
|||
const pageType = parseOriginalContent(url, input.originalContent)
|
||||
const metadata = await parseUrlMetadata(url)
|
||||
|
||||
const articleToSave = {
|
||||
const articleToSave: Page = {
|
||||
id: '',
|
||||
userId: ctx.uid,
|
||||
originalHtml: input.originalContent,
|
||||
content: content,
|
||||
description: metadata?.description || parseResult.parsedContent?.excerpt,
|
||||
|
|
@ -62,58 +61,27 @@ export const saveEmail = async (
|
|||
hash: stringToHash(content),
|
||||
image: metadata?.previewImage || parseResult.parsedContent?.previewImage,
|
||||
publishedAt: validatedDate(parseResult.parsedContent?.publishedDate),
|
||||
slug: slug,
|
||||
createdAt: new Date(),
|
||||
}
|
||||
|
||||
if (parseResult.canonicalUrl && parseResult.domContent) {
|
||||
// await ctx.pubsub.pageSaved(
|
||||
// saverId,
|
||||
// parseResult.canonicalUrl,
|
||||
// parseResult.domContent
|
||||
// )
|
||||
const page = await getPageByParam({ url: articleToSave.url })
|
||||
if (page) {
|
||||
const result = await updatePage(page.id, { archivedAt: null }, ctx)
|
||||
console.log('updated page from email', result)
|
||||
|
||||
return page
|
||||
}
|
||||
|
||||
const matchedUserArticleRecord = await ctx.models.userArticle.getByParameters(
|
||||
saverId,
|
||||
{
|
||||
articleUrl: articleToSave.url,
|
||||
}
|
||||
)
|
||||
const pageId = await createPage(articleToSave, ctx)
|
||||
if (!pageId) {
|
||||
console.log('failed to create new page')
|
||||
|
||||
let result: UserArticleData | undefined = undefined
|
||||
if (matchedUserArticleRecord) {
|
||||
// await ctx.pubsub.pageCreated(saverId, url, input.originalContent)
|
||||
|
||||
await kx.transaction(async (tx) => {
|
||||
await setClaims(tx, saverId)
|
||||
result = await ctx.models.userArticle.update(
|
||||
matchedUserArticleRecord.id,
|
||||
{
|
||||
savedAt: new Date(),
|
||||
archivedAt: null,
|
||||
}
|
||||
)
|
||||
})
|
||||
console.log('created matched email', result)
|
||||
} else {
|
||||
// await ctx.pubsub.pageCreated(saverId, url, input.originalContent)
|
||||
|
||||
await kx.transaction(async (tx) => {
|
||||
await setClaims(tx, saverId)
|
||||
|
||||
const articleRecord = await ctx.models.article.create(articleToSave, tx)
|
||||
result = await ctx.models.userArticle.create(
|
||||
{
|
||||
userId: saverId,
|
||||
slug: slug,
|
||||
articleId: articleRecord.id,
|
||||
articleUrl: articleRecord.url,
|
||||
articleHash: articleRecord.hash,
|
||||
},
|
||||
tx
|
||||
)
|
||||
console.log('created new email', result)
|
||||
})
|
||||
return undefined
|
||||
}
|
||||
|
||||
return result
|
||||
console.log('created new page from email', pageId)
|
||||
articleToSave.id = pageId
|
||||
|
||||
return articleToSave
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ type SaveContext = {
|
|||
cb: (tx: Knex.Transaction) => TResult,
|
||||
userRole?: string
|
||||
) => Promise<TResult>
|
||||
uid: string
|
||||
}
|
||||
|
||||
export const saveFile = async (
|
||||
|
|
@ -44,11 +45,7 @@ export const saveFile = async (
|
|||
}
|
||||
}
|
||||
|
||||
const savingRequest = await createSavingRequest(
|
||||
ctx,
|
||||
saver.id,
|
||||
input.clientRequestId
|
||||
)
|
||||
const savingRequest = await createSavingRequest(ctx, input.clientRequestId)
|
||||
|
||||
const uploadFileDetails = await getStorageFileDetails(
|
||||
input.uploadFileId,
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
import { MulticastMessage } from 'firebase-admin/messaging'
|
||||
import { kx } from '../datalayer/knex_config'
|
||||
import { createPubSubClient } from '../datalayer/pubsub'
|
||||
import { UserDeviceToken } from '../entity/user_device_tokens'
|
||||
import { env } from '../env'
|
||||
import { ContentReader } from '../generated/graphql'
|
||||
import { initModels } from '../server'
|
||||
import { analytics } from '../utils/analytics'
|
||||
import { sendMulticastPushNotifications } from '../utils/sendNotification'
|
||||
import { getNewsletterEmail } from './newsletters'
|
||||
import { SaveContext, saveEmail, SaveEmailInput } from './save_email'
|
||||
import { getDeviceTokensByUserId } from './user_device_tokens'
|
||||
import { getPageByParam } from '../elastic'
|
||||
import { Page } from '../elastic/types'
|
||||
import { addLabelToPage } from './labels'
|
||||
|
||||
interface NewsletterMessage {
|
||||
email: string
|
||||
|
|
@ -46,9 +44,10 @@ export const saveNewsletterEmail = async (
|
|||
})
|
||||
|
||||
const ctx: SaveContext = {
|
||||
models: initModels(kx, false),
|
||||
pubsub: createPubSubClient(),
|
||||
uid: newsletterEmail.user.id,
|
||||
}
|
||||
|
||||
const input: SaveEmailInput = {
|
||||
url: data.url,
|
||||
originalContent: data.content,
|
||||
|
|
@ -56,12 +55,19 @@ export const saveNewsletterEmail = async (
|
|||
author: data.author,
|
||||
}
|
||||
|
||||
const result = await saveEmail(ctx, newsletterEmail.user.id, input)
|
||||
if (!result) {
|
||||
const page = await saveEmail(ctx, input)
|
||||
if (!page) {
|
||||
console.log('newsletter not created:', input)
|
||||
return false
|
||||
}
|
||||
|
||||
// add newsletters label to page
|
||||
const result = await addLabelToPage(ctx, page.id, {
|
||||
name: 'Newsletter',
|
||||
color: '#07D2D1',
|
||||
})
|
||||
console.log('newsletter label added:', result)
|
||||
|
||||
// send push notification
|
||||
const deviceTokens = await getDeviceTokensByUserId(newsletterEmail.user.id)
|
||||
|
||||
|
|
@ -70,22 +76,8 @@ export const saveNewsletterEmail = async (
|
|||
return true
|
||||
}
|
||||
|
||||
const link = await getPageByParam({
|
||||
_id: result.articleId,
|
||||
userId: newsletterEmail.user.id,
|
||||
})
|
||||
|
||||
if (!link) {
|
||||
console.log(
|
||||
'Newsletter link not found:',
|
||||
newsletterEmail.user.id,
|
||||
result.articleId
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
if (deviceTokens.length) {
|
||||
const multicastMessage = messageForLink(link, deviceTokens)
|
||||
const multicastMessage = messageForLink(page, deviceTokens)
|
||||
await sendMulticastPushNotifications(
|
||||
newsletterEmail.user.id,
|
||||
multicastMessage,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { Page } from '../elastic/types'
|
|||
type SaveContext = {
|
||||
pubsub: PubsubClient
|
||||
models: DataModels
|
||||
uid: string
|
||||
}
|
||||
|
||||
type SaverUserData = {
|
||||
|
|
@ -56,11 +57,10 @@ const shouldParseInBackend = (input: SavePageInput): boolean => {
|
|||
|
||||
export const createSavingRequest = (
|
||||
ctx: SaveContext,
|
||||
userId: string,
|
||||
clientRequestId: string
|
||||
) => {
|
||||
return ctx.models.articleSavingRequest.create({
|
||||
userId: userId,
|
||||
userId: ctx.uid,
|
||||
id: clientRequestId,
|
||||
})
|
||||
}
|
||||
|
|
@ -70,11 +70,7 @@ export const savePage = async (
|
|||
saver: SaverUserData,
|
||||
input: SavePageInput
|
||||
): Promise<SaveResult> => {
|
||||
const savingRequest = await createSavingRequest(
|
||||
ctx,
|
||||
saver.userId,
|
||||
input.clientRequestId
|
||||
)
|
||||
const savingRequest = await createSavingRequest(ctx, input.clientRequestId)
|
||||
|
||||
const [slug, croppedPathname] = createSlug(input.url, input.title)
|
||||
const parseResult = await parsePreparedContent(input.url, {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,12 @@ import { Page, PageContext } from '../../src/elastic/types'
|
|||
import { createPubSubClient } from '../../src/datalayer/pubsub'
|
||||
|
||||
describe('elastic api', () => {
|
||||
const ctx: PageContext = { pubsub: createPubSubClient(), refresh: true }
|
||||
const userId = 'userId'
|
||||
const ctx: PageContext = {
|
||||
pubsub: createPubSubClient(),
|
||||
refresh: true,
|
||||
uid: userId,
|
||||
}
|
||||
|
||||
let page: Page
|
||||
|
||||
|
|
@ -59,7 +63,7 @@ describe('elastic api', () => {
|
|||
|
||||
after(async () => {
|
||||
// delete the testing page
|
||||
await deletePage(page.id, userId, ctx)
|
||||
await deletePage(page.id, ctx)
|
||||
})
|
||||
|
||||
describe('createPage', () => {
|
||||
|
|
@ -67,7 +71,7 @@ describe('elastic api', () => {
|
|||
|
||||
after(async () => {
|
||||
if (newPageId) {
|
||||
await deletePage(newPageId, userId, ctx)
|
||||
await deletePage(newPageId, ctx)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import { createPubSubClient } from '../../src/datalayer/pubsub'
|
|||
|
||||
chai.use(chaiString)
|
||||
|
||||
const ctx: PageContext = { pubsub: createPubSubClient(), refresh: true }
|
||||
const archiveLink = async (authToken: string, linkId: string) => {
|
||||
const query = `
|
||||
mutation {
|
||||
|
|
@ -244,6 +243,7 @@ describe('Article API', () => {
|
|||
const username = 'fakeUser'
|
||||
let authToken: string
|
||||
let user: User
|
||||
let ctx: PageContext
|
||||
|
||||
before(async () => {
|
||||
// create test user and login
|
||||
|
|
@ -253,6 +253,12 @@ describe('Article API', () => {
|
|||
.send({ fakeEmail: user.email })
|
||||
|
||||
authToken = res.body.authToken
|
||||
|
||||
ctx = {
|
||||
pubsub: createPubSubClient(),
|
||||
refresh: true,
|
||||
uid: user.id,
|
||||
}
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
|
|
@ -281,7 +287,7 @@ describe('Article API', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deletePage(pageId, user.id, ctx)
|
||||
await deletePage(pageId, ctx)
|
||||
})
|
||||
|
||||
it('should create an article', async () => {
|
||||
|
|
@ -320,7 +326,7 @@ describe('Article API', () => {
|
|||
|
||||
after(async () => {
|
||||
if (pageId) {
|
||||
await deletePage(pageId, user.id, ctx)
|
||||
await deletePage(pageId, ctx)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -386,11 +392,10 @@ describe('Article API', () => {
|
|||
}
|
||||
// create testing labels
|
||||
label = await createTestLabel(user, 'label', '#ffffff')
|
||||
// set label to a link
|
||||
// set label to the last page
|
||||
await updatePage(
|
||||
pages[0].id,
|
||||
pages[14].id,
|
||||
{
|
||||
...pages[0],
|
||||
labels: [{ id: label.id, name: label.name, color: label.color }],
|
||||
},
|
||||
ctx
|
||||
|
|
@ -401,15 +406,27 @@ describe('Article API', () => {
|
|||
query = articlesQuery(after)
|
||||
})
|
||||
|
||||
it('should return labels', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
context('when there are pages with labels', () => {
|
||||
before(() => {
|
||||
// get the last page
|
||||
after = '14'
|
||||
})
|
||||
|
||||
expect(res.body.data.articles.edges[0].node.labels[0].id).to.eql(label.id)
|
||||
it('should return labels', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
|
||||
expect(res.body.data.articles.edges[0].node.labels[0].id).to.eql(
|
||||
label.id
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
context('when we fetch the first page', () => {
|
||||
it('should return the first five items', async () => {
|
||||
before(() => {
|
||||
after = ''
|
||||
})
|
||||
|
||||
it('should return the first five items', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
|
||||
expect(res.body.data.articles.edges.length).to.eql(5)
|
||||
|
|
@ -421,7 +438,6 @@ describe('Article API', () => {
|
|||
})
|
||||
|
||||
it('should set the pageInfo', async () => {
|
||||
after = ''
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
expect(res.body.data.articles.pageInfo.endCursor).to.eql('5')
|
||||
expect(res.body.data.articles.pageInfo.startCursor).to.eql('')
|
||||
|
|
@ -564,7 +580,7 @@ describe('Article API', () => {
|
|||
|
||||
after(async () => {
|
||||
if (pageId) {
|
||||
await deletePage(pageId, user.id, ctx)
|
||||
await deletePage(pageId, ctx)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -612,7 +628,7 @@ describe('Article API', () => {
|
|||
|
||||
after(async () => {
|
||||
if (pageId) {
|
||||
await deletePage(pageId, user.id, ctx)
|
||||
await deletePage(pageId, ctx)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ import { User } from '../../src/entity/user'
|
|||
import chaiString from 'chai-string'
|
||||
import { deletePage } from '../../src/elastic'
|
||||
import { createPubSubClient } from '../../src/datalayer/pubsub'
|
||||
import { PageContext } from '../../src/elastic/types'
|
||||
|
||||
chai.use(chaiString)
|
||||
|
||||
const ctx = { pubsub: createPubSubClient() }
|
||||
const createHighlightQuery = (
|
||||
authToken: string,
|
||||
linkId: string,
|
||||
|
|
@ -57,6 +57,7 @@ describe('Highlights API', () => {
|
|||
let authToken: string
|
||||
let user: User
|
||||
let pageId: string
|
||||
let ctx: PageContext
|
||||
|
||||
before(async () => {
|
||||
// create test user and login
|
||||
|
|
@ -67,12 +68,13 @@ describe('Highlights API', () => {
|
|||
|
||||
authToken = res.body.authToken
|
||||
pageId = (await createTestElasticPage(user)).id
|
||||
ctx = { pubsub: createPubSubClient(), uid: user.id }
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(username)
|
||||
if (pageId) {
|
||||
await deletePage(pageId, user.id, ctx)
|
||||
await deletePage(pageId, ctx)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,10 @@
|
|||
import 'mocha'
|
||||
import { expect } from 'chai'
|
||||
import 'chai/register-should'
|
||||
import {
|
||||
createTestUser,
|
||||
deleteTestUser,
|
||||
} from '../db'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { SaveContext, saveEmail } from '../../src/services/save_email'
|
||||
import { getRepository } from 'typeorm'
|
||||
import { Link } from '../../src/entity/link'
|
||||
import { initModels } from '../../src/server'
|
||||
import { kx } from '../../src/datalayer/knex_config'
|
||||
import { createPubSubClient } from '../../src/datalayer/pubsub'
|
||||
import { getPageByParam } from '../../src/elastic'
|
||||
|
||||
describe('saveEmail', () => {
|
||||
const username = 'fakeUser'
|
||||
|
|
@ -21,11 +15,11 @@ describe('saveEmail', () => {
|
|||
it('doesnt fail if saved twice', async () => {
|
||||
const user = await createTestUser(username)
|
||||
const ctx: SaveContext = {
|
||||
models: initModels(kx, false),
|
||||
pubsub: createPubSubClient(),
|
||||
uid: user.id,
|
||||
}
|
||||
|
||||
await saveEmail(ctx, user.id, {
|
||||
await saveEmail(ctx, {
|
||||
originalContent: 'fake content',
|
||||
url: 'https://example.com',
|
||||
title: 'fake title',
|
||||
|
|
@ -34,7 +28,7 @@ describe('saveEmail', () => {
|
|||
|
||||
// This ensures row level security doesnt prevent
|
||||
// resaving the same URL
|
||||
const secondResult = await saveEmail(ctx, user.id, {
|
||||
const secondResult = await saveEmail(ctx, {
|
||||
originalContent: 'fake content',
|
||||
url: 'https://example.com',
|
||||
title: 'fake title',
|
||||
|
|
@ -42,17 +36,15 @@ describe('saveEmail', () => {
|
|||
})
|
||||
expect(secondResult).to.not.be.undefined
|
||||
|
||||
const links = await getRepository(Link).find({
|
||||
where: {
|
||||
user: user,
|
||||
},
|
||||
relations: ['page'],
|
||||
setTimeout(async () => {
|
||||
const page = await getPageByParam({ userId: user.id })
|
||||
if (!page) {
|
||||
expect.fail('page not found')
|
||||
}
|
||||
expect(page.url).to.equal('https://example.com')
|
||||
expect(page.title).to.equal('fake title')
|
||||
expect(page.author).to.equal('fake author')
|
||||
expect(page.content).to.contain('fake content')
|
||||
})
|
||||
|
||||
expect(links.length).to.equal(1)
|
||||
expect(links[0].page.url).to.equal('https://example.com')
|
||||
expect(links[0].page.title).to.equal('fake title')
|
||||
expect(links[0].page.author).to.equal('fake author')
|
||||
expect(links[0].page.content).to.contain('fake content')
|
||||
}).timeout(10000)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
import 'mocha'
|
||||
import { expect } from 'chai'
|
||||
import 'chai/register-should'
|
||||
import {
|
||||
createTestUser,
|
||||
deleteTestUser,
|
||||
} from '../db'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createNewsletterEmail } from '../../src/services/newsletters'
|
||||
import { saveNewsletterEmail } from '../../src/services/save_newsletter_email'
|
||||
import { getRepository } from 'typeorm'
|
||||
import { Link } from '../../src/entity/link'
|
||||
import { getPageByParam } from '../../src/elastic'
|
||||
|
||||
describe('saveNewsletterEmail', () => {
|
||||
const username = 'fakeUser'
|
||||
|
|
@ -28,17 +24,15 @@ describe('saveNewsletterEmail', () => {
|
|||
author: 'fake author',
|
||||
})
|
||||
|
||||
const links = await getRepository(Link).find({
|
||||
where: {
|
||||
user: user,
|
||||
},
|
||||
relations: ['page'],
|
||||
setTimeout(async () => {
|
||||
const page = await getPageByParam({ userId: user.id })
|
||||
if (!page) {
|
||||
expect.fail('page not found')
|
||||
}
|
||||
expect(page.url).to.equal('https://example.com')
|
||||
expect(page.title).to.equal('fake title')
|
||||
expect(page.author).to.equal('fake author')
|
||||
expect(page.content).to.contain('fake content')
|
||||
})
|
||||
|
||||
expect(links.length).to.equal(1)
|
||||
expect(links[0].page.url).to.equal('https://example.com')
|
||||
expect(links[0].page.title).to.equal('fake title')
|
||||
expect(links[0].page.author).to.equal('fake author')
|
||||
expect(links[0].page.content).to.contain('fake content')
|
||||
}).timeout(10000)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ export const createTestElasticPage = async (
|
|||
const pageId = await createPage(page, {
|
||||
pubsub: createPubSubClient(),
|
||||
refresh: true,
|
||||
uid: user.id,
|
||||
})
|
||||
if (pageId) {
|
||||
page.id = pageId
|
||||
|
|
|
|||
Loading…
Reference in a new issue