Skip to content

Commit

Permalink
Add+test page title update endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
poltak committed Feb 13, 2024
1 parent 4a51acf commit 29d0149
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 3 deletions.
2 changes: 1 addition & 1 deletion external/@worldbrain/memex-common
29 changes: 28 additions & 1 deletion src/page-indexing/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ import {
PipelineRes,
} from 'src/search/types'
import { extractUrlParts } from '@worldbrain/memex-common/lib/url-utils/extract-parts'
import pagePipeline from '@worldbrain/memex-common/lib/page-indexing/pipeline'
import pagePipeline, {
extractTerms,
} from '@worldbrain/memex-common/lib/page-indexing/pipeline'
import { initErrHandler } from 'src/search/storage'
import { Page, PageCreationProps, PageCreationOpts } from 'src/search'
import { DexieUtilsPlugin } from 'src/search/plugins'
Expand Down Expand Up @@ -120,6 +122,9 @@ export class PageIndexingBackground {
})

this.remoteFunctions = {
updatePageTitle: remoteFunctionWithExtraArgs((info, params) =>
this.updatePageTitle(params),
),
initContentIdentifier: remoteFunctionWithExtraArgs((info, params) =>
this.initContentIdentifier({
...params,
Expand Down Expand Up @@ -376,6 +381,28 @@ export class PageIndexingBackground {
await this.storage.createVisitsIfNeeded(pageData.url, visits)
}

async updatePageTitle(params: {
normaliedPageUrl: string
title: string
}): Promise<void> {
const title = params.title.trim()
if (!title.length) {
throw new Error(`Cannot set empty title`)
}
const existingPage = await this.storage.getPage(params.normaliedPageUrl)
if (!existingPage) {
throw new Error(`Cannot update title for non-existent page`)
}
await this.storage.updatePage(
{
...existingPage,
fullTitle: title,
titleTerms: [...extractTerms(title)],
},
existingPage,
)
}

async addFavIconIfNeeded(url: string, favIcon: string) {
const { hostname } = extractUrlParts(url)

Expand Down
2 changes: 1 addition & 1 deletion src/page-indexing/background/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from '@worldbrain/storex-pattern-modules'
import { COLLECTION_DEFINITIONS as PAGE_COLLECTION_DEFINITIONS } from '@worldbrain/memex-common/lib/storage/modules/pages/constants'
import { normalizeUrl } from '@worldbrain/memex-common/lib/url-utils/normalize'
import { PageCreationProps, PipelineRes, VisitInteraction } from 'src/search'
import type { PipelineRes, VisitInteraction } from 'src/search'
import { initErrHandler } from 'src/search/storage'
import { getTermsField } from '@worldbrain/memex-common/lib/storage/utils'
import {
Expand Down
4 changes: 4 additions & 0 deletions src/page-indexing/background/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export interface PageIndexingInterface<Role extends RemoteFunctionRole> {
{ fullPageUrl: string },
string | null
>
updatePageTitle: RemoteFunctionWithExtraArgs<
Role,
{ normaliedPageUrl: string; title: string }
>
}

export interface InitContentIdentifierParams {
Expand Down
112 changes: 112 additions & 0 deletions src/personal-cloud/background/backend/translation-layer/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ import omit from 'lodash/omit'
import { ROOT_NODE_PARENT_ID } from '@worldbrain/memex-common/lib/content-sharing/tree-utils'
import type { ListTree } from 'src/custom-lists/background/types'
import delay from 'src/util/delay'
import { mergeTermFields } from '@worldbrain/memex-common/lib/page-indexing/utils'
import type { PipelineRes } from 'src/search'
import { extractTerms } from '@worldbrain/memex-common/lib/page-indexing/pipeline'

const isFBEmu = process.env.TEST_SERVER_STORAGE === 'firebase-emulator'

Expand Down Expand Up @@ -588,6 +591,115 @@ describe('Personal cloud translation layer', () => {
testSyncPushTrigger,
} = await setup()

testSyncPushTrigger({ wasTriggered: false })
await insertTestPages(setups[0].storageManager)
// Add a shared annotation to trigger creation of sharedPageInfo for our page
await setups[0].storageManager
.collection('annotations')
.createObject(LOCAL_TEST_DATA_V24.annotations.first)
await setups[0].storageManager
.collection('sharedAnnotationMetadata')
.createObject(
LOCAL_TEST_DATA_V24.sharedAnnotationMetadata.first,
)
const updatedTitle = 'Updated title'

const localPage: PipelineRes = await setups[0].storageManager
.collection('pages')
.findOneObject({
url: LOCAL_TEST_DATA_V24.pages.first.url,
})
expect(localPage).toEqual({
...LOCAL_TEST_DATA_V24.pages.first,
titleTerms: expect.any(Array),
urlTerms: expect.any(Array),
})

await setups[0].backgroundModules.pages.updatePageTitle({
normaliedPageUrl: LOCAL_TEST_DATA_V24.pages.first.url,
title: updatedTitle,
})
expect(
await setups[0].storageManager
.collection('pages')
.findOneObject({
url: LOCAL_TEST_DATA_V24.pages.first.url,
}),
).toEqual({
...LOCAL_TEST_DATA_V24.pages.first,
fullTitle: updatedTitle,
titleTerms: mergeTermFields(
'titleTerms',
{ titleTerms: extractTerms(updatedTitle) },
{ titleTerms: localPage.titleTerms },
),
urlTerms: expect.any(Array),
})

await setups[0].backgroundModules.personalCloud.waitForSync()

const remoteData = serverIdCapturer.mergeIds(REMOTE_TEST_DATA_V24)
const testMetadata = remoteData.personalContentMetadata
const testLocators = remoteData.personalContentLocator

// prettier-ignore
expect(
await getDatabaseContents([
// 'dataUsageEntry',
'personalDataChange',
'personalBlockStats',
'personalContentMetadata',
'personalContentLocator',
'sharedPageInfo',
], { getWhere: getPersonalWhere }),
).toEqual({
...personalDataChanges(remoteData, [
[DataChangeType.Modify, 'personalContentMetadata', testMetadata.first.id],
], { skipChanges: 7 }),
personalBlockStats: [personalBlockStats({ usedBlocks: 3 })],
personalContentMetadata: [
{
...testMetadata.first,
title: updatedTitle,
},
testMetadata.second,
],
personalContentLocator: [testLocators.first, testLocators.second],
sharedPageInfo: [{
id: expect.anything(),
creator: TEST_USER.id,
fullTitle: updatedTitle,
normalizedUrl: localPage.url,
originalUrl: localPage.fullUrl,
updatedWhen: expect.anything(),
createdWhen: expect.anything(),
}],
})
// prettier-ignore
await testDownload([
{
type: PersonalCloudUpdateType.Overwrite, collection: 'pages', object: {
...LOCAL_TEST_DATA_V24.pages.first,
fullTitle: updatedTitle
}
},
], { skip: 4 })
testSyncPushTrigger({ wasTriggered: true })
})

it('should update page titles', async () => {
const {
setups,
serverIdCapturer,
serverStorageManager,
getPersonalWhere,
personalDataChanges,
personalBlockStats,
getDatabaseContents,
testDownload,
testSyncPushTrigger,
} = await setup()

testSyncPushTrigger({ wasTriggered: false })
await insertTestPages(setups[0].storageManager)
await setups[0].storageManager.collection('pages').updateObjects(
Expand Down

0 comments on commit 29d0149

Please sign in to comment.