mirror of
https://github.com/tutao/tutanota.git
synced 2025-10-19 07:53:47 +00:00
fix tests part 1
This commit is contained in:
parent
f3308a062d
commit
d4de59d7ce
5 changed files with 51 additions and 116 deletions
|
@ -5,6 +5,7 @@ import { FolderSystem } from "../../../common/api/common/mail/FolderSystem.js"
|
||||||
import {
|
import {
|
||||||
assertNotNull,
|
assertNotNull,
|
||||||
collectToMap,
|
collectToMap,
|
||||||
|
downcast,
|
||||||
getFirstOrThrow,
|
getFirstOrThrow,
|
||||||
groupBy,
|
groupBy,
|
||||||
groupByAndMap,
|
groupByAndMap,
|
||||||
|
@ -233,13 +234,12 @@ export class MailModel {
|
||||||
return mailboxDetail && this.inboxRuleHandler()?.findAndApplyMatchingRule(mailboxDetail, mail, isLeaderClient)
|
return mailboxDetail && this.inboxRuleHandler()?.findAndApplyMatchingRule(mailboxDetail, mail, isLeaderClient)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!isWebClient()) {
|
if (isWebClient()) {
|
||||||
const mailDetails = await this.mailFacade.loadMailDetailsBlob(mail)
|
|
||||||
this.spamHandler().storeTrainingDatum(mail, mailDetails)
|
|
||||||
} else {
|
|
||||||
// we only need to show notifications explicitly on the webapp
|
// we only need to show notifications explicitly on the webapp
|
||||||
this._showNotification(isRuleTargetFolder ?? sourceMailFolder, mail)
|
this._showNotification(isRuleTargetFolder ?? sourceMailFolder, mail)
|
||||||
}
|
} else {
|
||||||
|
const mailDetails = await this.mailFacade.loadMailDetailsBlob(mail)
|
||||||
|
this.spamHandler().storeTrainingDatum(mail, mailDetails)
|
||||||
|
|
||||||
if (isRuleTargetFolder) {
|
if (isRuleTargetFolder) {
|
||||||
return { processingDone: Promise.resolve() }
|
return { processingDone: Promise.resolve() }
|
||||||
|
@ -249,8 +249,9 @@ export class MailModel {
|
||||||
) {
|
) {
|
||||||
const folderSystem = this.getFolderSystemByGroupId(assertNotNull(mail._ownerGroup))
|
const folderSystem = this.getFolderSystemByGroupId(assertNotNull(mail._ownerGroup))
|
||||||
if (sourceMailFolder && folderSystem) {
|
if (sourceMailFolder && folderSystem) {
|
||||||
const predictPromise = this.spamHandler().predictSpamForNewMail(mail, sourceMailFolder, folderSystem)
|
const predictPromise = this.spamHandler().predictSpamForNewMail(mail, mailDetails, sourceMailFolder, folderSystem)
|
||||||
return { processingDone: predictPromise }
|
return { processingDone: downcast(predictPromise) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,9 +60,7 @@ export class SpamClassificationHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async predictSpamForNewMail(mail: Mail, folder: MailFolder, folderSystem: FolderSystem): Promise<void> {
|
public async predictSpamForNewMail(mail: Mail, mailDetails: MailDetails, sourceFolder: MailFolder, folderSystem: FolderSystem): Promise<MailFolder> {
|
||||||
const mailDetails = await this.mailFacade.loadMailDetailsBlob(mail)
|
|
||||||
|
|
||||||
const spamPredMailDatum: SpamPredMailDatum = {
|
const spamPredMailDatum: SpamPredMailDatum = {
|
||||||
subject: mail.subject,
|
subject: mail.subject,
|
||||||
body: getMailBodyText(mailDetails.body),
|
body: getMailBodyText(mailDetails.body),
|
||||||
|
@ -70,7 +68,7 @@ export class SpamClassificationHandler {
|
||||||
}
|
}
|
||||||
const isSpam = (await this.spamClassifier?.predict(spamPredMailDatum)) ?? null
|
const isSpam = (await this.spamClassifier?.predict(spamPredMailDatum)) ?? null
|
||||||
|
|
||||||
if (isSpam && folder.folderType === MailSetKind.INBOX) {
|
if (isSpam && sourceFolder.folderType === MailSetKind.INBOX) {
|
||||||
const spamFolder = assertNotNull(folderSystem.getSystemFolderByType(MailSetKind.SPAM))
|
const spamFolder = assertNotNull(folderSystem.getSystemFolderByType(MailSetKind.SPAM))
|
||||||
if (this.spamMoveMailData) {
|
if (this.spamMoveMailData) {
|
||||||
this.spamMoveMailData.mails.push(mail._id)
|
this.spamMoveMailData.mails.push(mail._id)
|
||||||
|
@ -83,7 +81,8 @@ export class SpamClassificationHandler {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.sendMoveMailServiceRequest(this.mailFacade)
|
this.sendMoveMailServiceRequest(this.mailFacade)
|
||||||
} else if (!isSpam && folder.folderType === MailSetKind.SPAM) {
|
return spamFolder
|
||||||
|
} else if (!isSpam && sourceFolder.folderType === MailSetKind.SPAM) {
|
||||||
const hamFolder = assertNotNull(folderSystem.getSystemFolderByType(MailSetKind.INBOX))
|
const hamFolder = assertNotNull(folderSystem.getSystemFolderByType(MailSetKind.INBOX))
|
||||||
if (this.hamMoveMailData) {
|
if (this.hamMoveMailData) {
|
||||||
this.hamMoveMailData.mails.push(mail._id)
|
this.hamMoveMailData.mails.push(mail._id)
|
||||||
|
@ -96,9 +95,11 @@ export class SpamClassificationHandler {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.sendMoveMailServiceRequest(this.mailFacade)
|
this.sendMoveMailServiceRequest(this.mailFacade)
|
||||||
|
return hamFolder
|
||||||
} else {
|
} else {
|
||||||
this.classifierResultServiceMailIds.push(mail._id)
|
this.classifierResultServiceMailIds.push(mail._id)
|
||||||
this.sendClassifierResultServiceRequest(this.mailFacade)
|
this.sendClassifierResultServiceRequest(this.mailFacade)
|
||||||
|
return sourceFolder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
GroupType,
|
GroupType,
|
||||||
PermissionType,
|
PermissionType,
|
||||||
PresentableKeyVerificationState,
|
PresentableKeyVerificationState,
|
||||||
|
ProcessingState,
|
||||||
PublicKeyIdentifierType,
|
PublicKeyIdentifierType,
|
||||||
} from "../../../../../src/common/api/common/TutanotaConstants.js"
|
} from "../../../../../src/common/api/common/TutanotaConstants.js"
|
||||||
import {
|
import {
|
||||||
|
@ -1854,7 +1855,7 @@ o.spec("CryptoFacadeTest", function () {
|
||||||
mailDetailsDraft: null,
|
mailDetailsDraft: null,
|
||||||
sets: [],
|
sets: [],
|
||||||
keyVerificationState: null,
|
keyVerificationState: null,
|
||||||
isInboxRuleApplied: true,
|
processingState: ProcessingState.INBOX_RULE_APPLIED,
|
||||||
clientSpamClassifierResult: null,
|
clientSpamClassifierResult: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import o from "@tutao/otest"
|
import o from "@tutao/otest"
|
||||||
import { Notifications } from "../../../src/common/gui/Notifications.js"
|
import { Notifications } from "../../../src/common/gui/Notifications.js"
|
||||||
import { mock, Spy, spy, verify } from "@tutao/tutanota-test-utils"
|
import { mock, Spy, spy, verify } from "@tutao/tutanota-test-utils"
|
||||||
import { MailSetKind, OperationType } from "../../../src/common/api/common/TutanotaConstants.js"
|
import { MailSetKind, OperationType, ProcessingState } from "../../../src/common/api/common/TutanotaConstants.js"
|
||||||
import {
|
import {
|
||||||
BodyTypeRef,
|
BodyTypeRef,
|
||||||
Mail,
|
Mail,
|
||||||
MailDetails,
|
MailDetails,
|
||||||
|
MailDetailsBlob,
|
||||||
MailDetailsBlobTypeRef,
|
MailDetailsBlobTypeRef,
|
||||||
MailDetailsTypeRef,
|
MailDetailsTypeRef,
|
||||||
MailFolderTypeRef,
|
MailFolderTypeRef,
|
||||||
MailSetEntryTypeRef,
|
|
||||||
MailTypeRef,
|
MailTypeRef,
|
||||||
} from "../../../src/common/api/entities/tutanota/TypeRefs.js"
|
} from "../../../src/common/api/entities/tutanota/TypeRefs.js"
|
||||||
import { EntityClient } from "../../../src/common/api/common/EntityClient.js"
|
import { EntityClient } from "../../../src/common/api/common/EntityClient.js"
|
||||||
|
@ -84,29 +84,29 @@ o.spec("MailModelTest", function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
o("doesn't send notification for another folder", async function () {
|
o("doesn't send notification for another folder", async function () {
|
||||||
const mailSetEntry = createTestEntity(MailSetEntryTypeRef, { _id: [anotherFolder.entries, "mailSetEntryId"] })
|
const mail = createTestEntity(MailTypeRef, { _id: ["mailBagListId", "mailId"], sets: [] })
|
||||||
restClient.addListInstances(mailSetEntry)
|
restClient.addListInstances(mail)
|
||||||
await model.entityEventsReceived([
|
await model.entityEventsReceived([
|
||||||
makeUpdate({
|
makeUpdate({
|
||||||
instanceListId: getListId(mailSetEntry) as NonEmptyString,
|
instanceListId: getListId(mail) as NonEmptyString,
|
||||||
instanceId: getElementId(mailSetEntry),
|
instanceId: getElementId(mail),
|
||||||
operation: OperationType.CREATE,
|
operation: OperationType.CREATE,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
o(showSpy.invocations.length).equals(0)
|
o(showSpy.invocations.length).equals(0)
|
||||||
})
|
})
|
||||||
o("doesn't send notification for move operation", async function () {
|
o("doesn't send notification for move operation", async function () {
|
||||||
const mailSetEntry = createTestEntity(MailSetEntryTypeRef, { _id: [inboxFolder.entries, "mailSetEntryId"] })
|
const mail = createTestEntity(MailTypeRef, { _id: ["mailBagListId", "mailId"], sets: [] })
|
||||||
restClient.addListInstances(mailSetEntry)
|
restClient.addListInstances(mail)
|
||||||
await model.entityEventsReceived([
|
await model.entityEventsReceived([
|
||||||
makeUpdate({
|
makeUpdate({
|
||||||
instanceListId: getListId(mailSetEntry) as NonEmptyString,
|
instanceListId: getListId(mail) as NonEmptyString,
|
||||||
instanceId: getElementId(mailSetEntry),
|
instanceId: getElementId(mail),
|
||||||
operation: OperationType.DELETE,
|
operation: OperationType.DELETE,
|
||||||
}),
|
}),
|
||||||
makeUpdate({
|
makeUpdate({
|
||||||
instanceListId: getListId(mailSetEntry) as NonEmptyString,
|
instanceListId: getListId(mail) as NonEmptyString,
|
||||||
instanceId: getElementId(mailSetEntry),
|
instanceId: getElementId(mail),
|
||||||
operation: OperationType.CREATE,
|
operation: OperationType.CREATE,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
@ -145,14 +145,18 @@ o.spec("MailModelTest", function () {
|
||||||
_ownerGroup: "mailGroup",
|
_ownerGroup: "mailGroup",
|
||||||
mailDetails: ["detailsList", mailDetails._id],
|
mailDetails: ["detailsList", mailDetails._id],
|
||||||
sets: [inboxFolder._id],
|
sets: [inboxFolder._id],
|
||||||
|
processingState: ProcessingState.INBOX_RULE_NOT_PROCESSED,
|
||||||
})
|
})
|
||||||
const mailDetailsBlob = createTestEntity(MailDetailsBlobTypeRef, {
|
const mailDetailsBlob: MailDetailsBlob = createTestEntity(MailDetailsBlobTypeRef, {
|
||||||
_id: mail.mailDetails!,
|
_id: mail.mailDetails!,
|
||||||
details: mailDetails,
|
details: mailDetails,
|
||||||
})
|
})
|
||||||
|
|
||||||
restClient.addListInstances(mail)
|
restClient.addListInstances(mail)
|
||||||
restClient.addBlobInstances(mailDetailsBlob)
|
restClient.addBlobInstances(mailDetailsBlob)
|
||||||
|
|
||||||
|
when(mailFacade.loadMailDetailsBlob(mail)).thenResolve(mailDetails)
|
||||||
|
|
||||||
modelWithSpamAndInboxRule = mock(
|
modelWithSpamAndInboxRule = mock(
|
||||||
new MailModel(
|
new MailModel(
|
||||||
downcast({}),
|
downcast({}),
|
||||||
|
@ -204,6 +208,7 @@ o.spec("MailModelTest", function () {
|
||||||
await processingDone
|
await processingDone
|
||||||
verify(spamClassifier.predict(anything()), { times: 0 })
|
verify(spamClassifier.predict(anything()), { times: 0 })
|
||||||
})
|
})
|
||||||
|
|
||||||
o("spam prediction happens when inbox rule is not applied", async () => {
|
o("spam prediction happens when inbox rule is not applied", async () => {
|
||||||
when(spamClassifier.predict(anything())).thenResolve(false)
|
when(spamClassifier.predict(anything())).thenResolve(false)
|
||||||
|
|
||||||
|
@ -217,19 +222,6 @@ o.spec("MailModelTest", function () {
|
||||||
await processingDone
|
await processingDone
|
||||||
verify(spamClassifier.predict(anything()), { times: 1 })
|
verify(spamClassifier.predict(anything()), { times: 1 })
|
||||||
})
|
})
|
||||||
o("spam prediction happens when inbox rule throws", async () => {
|
|
||||||
when(spamClassifier.predict(anything())).thenResolve(false)
|
|
||||||
|
|
||||||
const mailCreateEvent = makeUpdate({
|
|
||||||
instanceListId: "mailListId",
|
|
||||||
instanceId: "mailId",
|
|
||||||
operation: OperationType.CREATE,
|
|
||||||
})
|
|
||||||
when(inboxRuleHandler.findAndApplyMatchingRule(anything(), anything(), anything())).thenReject(new Error("Some error for inbox rule"))
|
|
||||||
const { processingDone } = await modelWithSpamAndInboxRule.entityEventsReceived([mailCreateEvent])
|
|
||||||
await processingDone
|
|
||||||
verify(spamClassifier.predict(anything()), { times: 1 })
|
|
||||||
})
|
|
||||||
|
|
||||||
o("does not try to do spam classification when downloading of mail fails on create mail event", async function () {
|
o("does not try to do spam classification when downloading of mail fails on create mail event", async function () {
|
||||||
when(inboxRuleHandler.findAndApplyMatchingRule(anything(), anything(), anything())).thenResolve(null)
|
when(inboxRuleHandler.findAndApplyMatchingRule(anything(), anything(), anything())).thenResolve(null)
|
||||||
|
@ -252,25 +244,6 @@ o.spec("MailModelTest", function () {
|
||||||
verify(spamClassifier.predict(anything()), { times: 1 })
|
verify(spamClassifier.predict(anything()), { times: 1 })
|
||||||
})
|
})
|
||||||
|
|
||||||
o("no spam prediction for draft mails", async () => {
|
|
||||||
mail.mailDetails = null
|
|
||||||
mail.mailDetailsDraft = ["draftListId", "draftId"]
|
|
||||||
restClient.addListInstances(mail)
|
|
||||||
|
|
||||||
when(inboxRuleHandler.findAndApplyMatchingRule(anything(), mail, anything())).thenResolve(inboxFolder)
|
|
||||||
|
|
||||||
const mailCreateEvent = makeUpdate({
|
|
||||||
instanceListId: "mailListId",
|
|
||||||
instanceId: "mailId",
|
|
||||||
operation: OperationType.CREATE,
|
|
||||||
})
|
|
||||||
const { processingDone } = await modelWithSpamAndInboxRule.entityEventsReceived([mailCreateEvent])
|
|
||||||
await processingDone
|
|
||||||
|
|
||||||
verify(spamClassificationHandler.predictSpamForNewMail(mail, anything(), anything()), { times: 1 })
|
|
||||||
verify(spamClassifier.predict(anything()), { times: 0 })
|
|
||||||
})
|
|
||||||
|
|
||||||
o("deletes a training datum for deleted mail event", async () => {
|
o("deletes a training datum for deleted mail event", async () => {
|
||||||
const mailDeleteEvent = makeUpdate({
|
const mailDeleteEvent = makeUpdate({
|
||||||
instanceListId: "mailListId",
|
instanceListId: "mailListId",
|
||||||
|
|
|
@ -7,25 +7,19 @@ import {
|
||||||
Mail,
|
Mail,
|
||||||
MailDetails,
|
MailDetails,
|
||||||
MailDetailsTypeRef,
|
MailDetailsTypeRef,
|
||||||
MailFolder,
|
|
||||||
MailFolderTypeRef,
|
MailFolderTypeRef,
|
||||||
MailTypeRef,
|
MailTypeRef,
|
||||||
} from "../../../src/common/api/entities/tutanota/TypeRefs"
|
} from "../../../src/common/api/entities/tutanota/TypeRefs"
|
||||||
import { SpamClassifier, SpamTrainMailDatum } from "../../../src/mail-app/workerUtils/spamClassification/SpamClassifier"
|
import { SpamClassifier, SpamTrainMailDatum } from "../../../src/mail-app/workerUtils/spamClassification/SpamClassifier"
|
||||||
import { getMailBodyText } from "../../../src/common/api/common/CommonMailUtils"
|
import { getMailBodyText } from "../../../src/common/api/common/CommonMailUtils"
|
||||||
import { MailSetKind } from "../../../src/common/api/common/TutanotaConstants"
|
import { MailSetKind, ProcessingState } from "../../../src/common/api/common/TutanotaConstants"
|
||||||
import { ClientClassifierType } from "../../../src/common/api/common/ClientClassifierType"
|
import { ClientClassifierType } from "../../../src/common/api/common/ClientClassifierType"
|
||||||
import { assert, assertNotNull, defer, Nullable } from "@tutao/tutanota-utils"
|
import { assert, assertNotNull } from "@tutao/tutanota-utils"
|
||||||
import { MailFacade } from "../../../src/common/api/worker/facades/lazy/MailFacade"
|
import { MailFacade } from "../../../src/common/api/worker/facades/lazy/MailFacade"
|
||||||
import { createTestEntity } from "../TestUtils"
|
import { createTestEntity } from "../TestUtils"
|
||||||
import { SpamClassificationHandler } from "../../../src/mail-app/mail/model/SpamClassificationHandler"
|
import { SpamClassificationHandler } from "../../../src/mail-app/mail/model/SpamClassificationHandler"
|
||||||
import { EntityClient } from "../../../src/common/api/common/EntityClient"
|
|
||||||
import { ClientModelInfo } from "../../../src/common/api/common/EntityFunctions"
|
|
||||||
import { BulkMailLoader } from "../../../src/mail-app/workerUtils/index/BulkMailLoader"
|
|
||||||
import { EntityRestInterface } from "../../../src/common/api/worker/rest/EntityRestClient"
|
|
||||||
import { FolderSystem } from "../../../src/common/api/common/mail/FolderSystem"
|
import { FolderSystem } from "../../../src/common/api/common/mail/FolderSystem"
|
||||||
import { isSameId } from "../../../src/common/api/common/utils/EntityUtils"
|
import { isSameId } from "../../../src/common/api/common/utils/EntityUtils"
|
||||||
import { WebsocketConnectivityModel } from "../../../src/common/misc/WebsocketConnectivityModel"
|
|
||||||
|
|
||||||
const { anything } = matchers
|
const { anything } = matchers
|
||||||
|
|
||||||
|
@ -35,12 +29,8 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
let mail: Mail
|
let mail: Mail
|
||||||
let spamClassifier: SpamClassifier
|
let spamClassifier: SpamClassifier
|
||||||
let spamHandler: SpamClassificationHandler
|
let spamHandler: SpamClassificationHandler
|
||||||
let restClient: EntityRestInterface
|
|
||||||
let bulkMailLoader: BulkMailLoader
|
|
||||||
const inboxRuleOutcome = defer<Nullable<MailFolder>>()
|
|
||||||
let folderSystem: FolderSystem
|
let folderSystem: FolderSystem
|
||||||
let mailDetails: MailDetails
|
let mailDetails: MailDetails
|
||||||
let connectivityModel: WebsocketConnectivityModel
|
|
||||||
|
|
||||||
const inboxFolder = createTestEntity(MailFolderTypeRef, { _id: ["listId", "inbox"], folderType: MailSetKind.INBOX })
|
const inboxFolder = createTestEntity(MailFolderTypeRef, { _id: ["listId", "inbox"], folderType: MailSetKind.INBOX })
|
||||||
const trashFolder = createTestEntity(MailFolderTypeRef, { _id: ["listId", "trash"], folderType: MailSetKind.TRASH })
|
const trashFolder = createTestEntity(MailFolderTypeRef, { _id: ["listId", "trash"], folderType: MailSetKind.TRASH })
|
||||||
|
@ -48,7 +38,6 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
|
|
||||||
o.beforeEach(function () {
|
o.beforeEach(function () {
|
||||||
spamClassifier = object<SpamClassifier>()
|
spamClassifier = object<SpamClassifier>()
|
||||||
restClient = object<EntityRestInterface>()
|
|
||||||
|
|
||||||
body = createTestEntity(BodyTypeRef, { text: "Body Text" })
|
body = createTestEntity(BodyTypeRef, { text: "Body Text" })
|
||||||
mailDetails = createTestEntity(MailDetailsTypeRef, { _id: "mailDetail", body })
|
mailDetails = createTestEntity(MailDetailsTypeRef, { _id: "mailDetail", body })
|
||||||
|
@ -59,15 +48,11 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
_ownerGroup: "owner",
|
_ownerGroup: "owner",
|
||||||
mailDetails: ["detailsList", mailDetails._id],
|
mailDetails: ["detailsList", mailDetails._id],
|
||||||
unread: true,
|
unread: true,
|
||||||
isInboxRuleApplied: false,
|
processingState: ProcessingState.INBOX_RULE_NOT_PROCESSED,
|
||||||
clientSpamClassifierResult: null,
|
clientSpamClassifierResult: null,
|
||||||
})
|
})
|
||||||
bulkMailLoader = object<BulkMailLoader>()
|
|
||||||
folderSystem = object<FolderSystem>()
|
folderSystem = object<FolderSystem>()
|
||||||
|
|
||||||
connectivityModel = object<WebsocketConnectivityModel>()
|
|
||||||
when(connectivityModel.isLeader()).thenReturn(true)
|
|
||||||
|
|
||||||
when(mailFacade.simpleMoveMails(anything(), anything(), ClientClassifierType.CLIENT_CLASSIFICATION)).thenResolve([])
|
when(mailFacade.simpleMoveMails(anything(), anything(), ClientClassifierType.CLIENT_CLASSIFICATION)).thenResolve([])
|
||||||
when(folderSystem.getSystemFolderByType(MailSetKind.SPAM)).thenReturn(spamFolder)
|
when(folderSystem.getSystemFolderByType(MailSetKind.SPAM)).thenReturn(spamFolder)
|
||||||
when(folderSystem.getSystemFolderByType(MailSetKind.INBOX)).thenReturn(inboxFolder)
|
when(folderSystem.getSystemFolderByType(MailSetKind.INBOX)).thenReturn(inboxFolder)
|
||||||
|
@ -81,7 +66,7 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
else throw new Error("Unknown mail Folder")
|
else throw new Error("Unknown mail Folder")
|
||||||
})
|
})
|
||||||
when(
|
when(
|
||||||
bulkMailLoader.loadMailDetails(
|
mailFacade.loadMailDetailsBlob(
|
||||||
matchers.argThat((requestedMails: Array<Mail>) => {
|
matchers.argThat((requestedMails: Array<Mail>) => {
|
||||||
assert(requestedMails.length === 1, "exactly one mail is requested at a time")
|
assert(requestedMails.length === 1, "exactly one mail is requested at a time")
|
||||||
return isSameId(requestedMails[0]._id, mail._id)
|
return isSameId(requestedMails[0]._id, mail._id)
|
||||||
|
@ -89,14 +74,10 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
),
|
),
|
||||||
anything(),
|
anything(),
|
||||||
).thenDo(async () => [{ mail, mailDetails }])
|
).thenDo(async () => [{ mail, mailDetails }])
|
||||||
|
|
||||||
const entityClient = new EntityClient(restClient, ClientModelInfo.getNewInstanceForTestsOnly())
|
|
||||||
spamHandler = new SpamClassificationHandler(mailFacade, spamClassifier)
|
spamHandler = new SpamClassificationHandler(mailFacade, spamClassifier)
|
||||||
})
|
})
|
||||||
|
|
||||||
o("processSpam correctly verifies if email is stored in spam folder", async function () {
|
o("processSpam correctly verifies if email is stored in spam folder", async function () {
|
||||||
inboxRuleOutcome.resolve(null)
|
|
||||||
|
|
||||||
mail.sets = [spamFolder._id]
|
mail.sets = [spamFolder._id]
|
||||||
when(spamClassifier.predict(anything())).thenResolve(false)
|
when(spamClassifier.predict(anything())).thenResolve(false)
|
||||||
const expectedTrainingData: SpamTrainMailDatum = {
|
const expectedTrainingData: SpamTrainMailDatum = {
|
||||||
|
@ -108,7 +89,7 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
isSpamConfidence: 1,
|
isSpamConfidence: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalResult = await spamHandler.predictSpamForNewMail(mail, folderSystem)
|
const finalResult = await spamHandler.predictSpamForNewMail(mail, mailDetails, spamFolder, folderSystem)
|
||||||
verify(spamClassifier.storeSpamClassification(expectedTrainingData), { times: 1 })
|
verify(spamClassifier.storeSpamClassification(expectedTrainingData), { times: 1 })
|
||||||
verify(mailFacade.simpleMoveMails([mail._id], MailSetKind.INBOX, ClientClassifierType.CLIENT_CLASSIFICATION))
|
verify(mailFacade.simpleMoveMails([mail._id], MailSetKind.INBOX, ClientClassifierType.CLIENT_CLASSIFICATION))
|
||||||
o(finalResult).deepEquals(inboxFolder)
|
o(finalResult).deepEquals(inboxFolder)
|
||||||
|
@ -116,9 +97,8 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
|
|
||||||
o("does not classify mail if the mail has non null client classification result", async function () {
|
o("does not classify mail if the mail has non null client classification result", async function () {
|
||||||
mail.sets = [inboxFolder._id]
|
mail.sets = [inboxFolder._id]
|
||||||
mail.isInboxRuleApplied = false
|
mail.processingState = ProcessingState.INBOX_RULE_NOT_PROCESSED
|
||||||
mail.clientSpamClassifierResult = createTestEntity(ClientSpamClassifierResultTypeRef)
|
mail.clientSpamClassifierResult = createTestEntity(ClientSpamClassifierResultTypeRef)
|
||||||
inboxRuleOutcome.resolve(null)
|
|
||||||
|
|
||||||
const expectedTrainingData: SpamTrainMailDatum = {
|
const expectedTrainingData: SpamTrainMailDatum = {
|
||||||
mailId: mail._id,
|
mailId: mail._id,
|
||||||
|
@ -129,34 +109,14 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
isSpamConfidence: 0,
|
isSpamConfidence: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalResult = await spamHandler.predictSpamForNewMail(mail, folderSystem)
|
const finalResult = await spamHandler.predictSpamForNewMail(mail, mailDetails, inboxFolder, folderSystem)
|
||||||
o(finalResult).equals(null)
|
o(finalResult).equals(null)
|
||||||
verify(mailFacade.simpleMoveMails(anything(), anything(), anything()), { times: 0 })
|
verify(mailFacade.simpleMoveMails(anything(), anything(), anything()), { times: 0 })
|
||||||
verify(spamClassifier.predict(anything()), { times: 0 })
|
verify(spamClassifier.predict(anything()), { times: 0 })
|
||||||
verify(spamClassifier.storeSpamClassification(expectedTrainingData), { times: 1 })
|
verify(spamClassifier.storeSpamClassification(expectedTrainingData), { times: 1 })
|
||||||
})
|
})
|
||||||
|
|
||||||
o("mail in spam folder is not classified but stored with confidence 0", async function () {
|
|
||||||
inboxRuleOutcome.resolve(null)
|
|
||||||
mail.sets = [trashFolder._id]
|
|
||||||
|
|
||||||
const expectedTrainingData: SpamTrainMailDatum = {
|
|
||||||
mailId: mail._id,
|
|
||||||
subject: mail.subject,
|
|
||||||
body: getMailBodyText(body),
|
|
||||||
isSpam: false,
|
|
||||||
ownerGroup: "owner",
|
|
||||||
isSpamConfidence: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
const finalResult = await spamHandler.predictSpamForNewMail(inboxRuleOutcome.promise, mail, folderSystem)
|
|
||||||
o(finalResult).deepEquals(null)
|
|
||||||
verify(mailFacade.simpleMoveMails(anything(), anything(), anything()), { times: 0 })
|
|
||||||
verify(spamClassifier.storeSpamClassification(expectedTrainingData), { times: 1 })
|
|
||||||
})
|
|
||||||
|
|
||||||
o("processSpam moves mail to inbox when detected as such and its not already in inbox", async function () {
|
o("processSpam moves mail to inbox when detected as such and its not already in inbox", async function () {
|
||||||
inboxRuleOutcome.resolve(null)
|
|
||||||
when(spamClassifier.predict(anything())).thenResolve(false)
|
when(spamClassifier.predict(anything())).thenResolve(false)
|
||||||
|
|
||||||
mail.sets = [spamFolder._id]
|
mail.sets = [spamFolder._id]
|
||||||
|
@ -170,14 +130,13 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
ownerGroup: "owner",
|
ownerGroup: "owner",
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalResult = await spamHandler.predictSpamForNewMail(inboxRuleOutcome.promise, mail, folderSystem)
|
const finalResult = await spamHandler.predictSpamForNewMail(mail, mailDetails, spamFolder, folderSystem)
|
||||||
o(finalResult).deepEquals(inboxFolder)
|
o(finalResult).deepEquals(inboxFolder)
|
||||||
verify(spamClassifier.storeSpamClassification(expectedDatum), { times: 1 })
|
verify(spamClassifier.storeSpamClassification(expectedDatum), { times: 1 })
|
||||||
verify(mailFacade.simpleMoveMails([["listId", "elementId"]], MailSetKind.INBOX, ClientClassifierType.CLIENT_CLASSIFICATION), { times: 1 })
|
verify(mailFacade.simpleMoveMails([["listId", "elementId"]], MailSetKind.INBOX, ClientClassifierType.CLIENT_CLASSIFICATION), { times: 1 })
|
||||||
})
|
})
|
||||||
|
|
||||||
o("processSpam moves mail to spam when detected as such and its not already in spam", async function () {
|
o("processSpam moves mail to spam when detected as such and its not already in spam", async function () {
|
||||||
inboxRuleOutcome.resolve(null)
|
|
||||||
when(spamClassifier.predict(anything())).thenResolve(true)
|
when(spamClassifier.predict(anything())).thenResolve(true)
|
||||||
|
|
||||||
mail.sets = [inboxFolder._id]
|
mail.sets = [inboxFolder._id]
|
||||||
|
@ -190,7 +149,7 @@ o.spec("SpamClassificationHandlerTest", function () {
|
||||||
ownerGroup: "owner",
|
ownerGroup: "owner",
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalResult = await spamHandler.predictSpamForNewMail(inboxRuleOutcome.promise, mail, folderSystem)
|
const finalResult = await spamHandler.predictSpamForNewMail(mail, mailDetails, inboxFolder, folderSystem)
|
||||||
o(finalResult).deepEquals(spamFolder)
|
o(finalResult).deepEquals(spamFolder)
|
||||||
verify(spamClassifier.storeSpamClassification(expectedDatum), { times: 1 })
|
verify(spamClassifier.storeSpamClassification(expectedDatum), { times: 1 })
|
||||||
verify(mailFacade.simpleMoveMails([["listId", "elementId"]], MailSetKind.SPAM, ClientClassifierType.CLIENT_CLASSIFICATION), { times: 1 })
|
verify(mailFacade.simpleMoveMails([["listId", "elementId"]], MailSetKind.SPAM, ClientClassifierType.CLIENT_CLASSIFICATION), { times: 1 })
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue