Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions src/mail-app/mail/view/MailViewerViewModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export class MailViewerViewModel {

private contentBlockingStatus: ContentBlockingStatus | null = null

private errorOccurred: boolean = false
private errorOccurredWhileLoadingMailDetails: boolean = false
private loadedInlineImages: InlineImages | null = null
/** only loaded when showFolder is set to true */
private folderMailboxText: string | null
Expand Down Expand Up @@ -438,7 +438,7 @@ export class MailViewerViewModel {
if (this.mailDetails) {
bodyErrors = typeof downcast(this.mailDetails.body)._errors !== "undefined"
}
return this.errorOccurred || typeof this.mail._errors !== "undefined" || bodyErrors
return this.errorOccurredWhileLoadingMailDetails || typeof this.mail._errors !== "undefined" || bodyErrors
}

isTutanotaTeamMail(): boolean {
Expand Down Expand Up @@ -638,16 +638,17 @@ export class MailViewerViewModel {

try {
this.mailDetails = await loadMailDetails(this.mailFacade, this.mail)
this.errorOccurredWhileLoadingMailDetails = false
} catch (e) {
if (e instanceof NotFoundError) {
console.log("could load mail body as it has been moved/deleted already", e)
this.errorOccurred = true
this.errorOccurredWhileLoadingMailDetails = true
return []
}

if (e instanceof NotAuthorizedError) {
console.log("could load mail body as the permission is missing", e)
this.errorOccurred = true
this.errorOccurredWhileLoadingMailDetails = true
return []
}

Expand Down Expand Up @@ -732,8 +733,8 @@ export class MailViewerViewModel {

this.entityClient
.update(mail)
.catch(ofClass(LockedError, (e) => console.log("could not update mail phishing status as mail is locked")))
.catch(ofClass(NotFoundError, (e) => console.log("mail already moved")))
.catch(ofClass(LockedError, (_) => console.log("could not update mail phishing status as mail is locked")))
.catch(ofClass(NotFoundError, (_) => console.log("mail already moved")))

m.redraw()
}
Expand Down Expand Up @@ -1133,10 +1134,6 @@ export class MailViewerViewModel {
return this.mailModel.getLabelsForMail(this.mail)
}

private getMailOwnerGroup(): Id | null {
return this.mail._ownerGroup
}

private updateMail({ mail, showFolder }: { mail: Mail; showFolder?: boolean }) {
if (!isSameId(mail._id, this.mail._id)) {
throw new ProgrammingError(
Expand Down
71 changes: 65 additions & 6 deletions test/tests/mail/view/MailViewerViewModelTest.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import o from "@tutao/otest"
import { MailViewerViewModel } from "../../../../src/mail-app/mail/view/MailViewerViewModel.js"
import {
ConversationEntryTypeRef,
HeaderTypeRef,
Mail,
MailAddressTypeRef,
Expand All @@ -15,21 +16,24 @@ import { ConfigurationDatabase } from "../../../../src/common/api/worker/facades
import { LoginController } from "../../../../src/common/api/main/LoginController.js"
import { EventController } from "../../../../src/common/api/main/EventController.js"
import { WorkerFacade } from "../../../../src/common/api/worker/facades/WorkerFacade.js"
import { NotFoundError } from "../../../../src/common/api/common/error/RestError.js"
import { SearchModel } from "../../../../src/mail-app/search/model/SearchModel.js"
import { MailFacade } from "../../../../src/common/api/worker/facades/lazy/MailFacade.js"
import { FileController } from "../../../../src/common/file/FileController.js"
import { createTestEntity } from "../../TestUtils.js"
import { MailState } from "../../../../src/common/api/common/TutanotaConstants.js"
import { ExternalImageRule, MailState } from "../../../../src/common/api/common/TutanotaConstants.js"
import { GroupInfoTypeRef } from "../../../../src/common/api/entities/sys/TypeRefs.js"
import { CryptoFacade } from "../../../../src/common/api/worker/crypto/CryptoFacade.js"
import { ContactImporter } from "../../../../src/mail-app/contacts/ContactImporter.js"
import { MailboxDetail, MailboxModel } from "../../../../src/common/mailFunctionality/MailboxModel.js"
import { ContactModel } from "../../../../src/common/contactsFunctionality/ContactModel.js"
import { SendMailModel } from "../../../../src/common/mailFunctionality/SendMailModel.js"
import { MailModel } from "../../../../src/mail-app/mail/model/MailModel.js"
import { downcast } from "@tutao/tutanota-utils"

o.spec("MailViewerViewModel", function () {
let mail: Mail
let mailDetails: MailDetails
let showFolder: boolean = false
let entityClient: EntityClient

Expand Down Expand Up @@ -63,7 +67,7 @@ o.spec("MailViewerViewModel", function () {
mailFacade = object()
cryptoFacade = object()
contactImporter = object()
mail = prepareMailWithHeaders(mailFacade, headers)
prepareMailWithHeaders(mailFacade, headers)

return new MailViewerViewModel(
mail,
Expand Down Expand Up @@ -92,7 +96,7 @@ o.spec("MailViewerViewModel", function () {
address: "ma@tuta.com",
}),
]
const mail = createTestEntity(MailTypeRef, {
mail = createTestEntity(MailTypeRef, {
_id: ["mailListId", "mailId"],
listUnsubscribe: true,
mailDetails: ["mailDetailsListId", "mailDetailsId"],
Expand All @@ -102,22 +106,31 @@ o.spec("MailViewerViewModel", function () {
address: "sender@list.com",
}),
})
const mailDetails: MailDetails = createTestEntity(MailDetailsTypeRef, {
mailDetails = createTestEntity(MailDetailsTypeRef, {
headers: createTestEntity(HeaderTypeRef, {
headers,
}),
recipients: createTestEntity(RecipientsTypeRef, {
toRecipients,
}),
body: object(),
})
mailDetails.body.text = "Hello World"
mailDetails.body.compressedText = null
downcast(mailDetails.body)._errors = undefined
when(mailFacade.loadMailDetailsBlob(mail)).thenResolve(mailDetails)
return mail
when(configFacade.getExternalImageRule(mail.sender.address)).thenResolve(ExternalImageRule.None)
when(mailModel.checkMailForPhishing(matchers.anything(), matchers.anything())).thenResolve(false)
when(entityClient.load(ConversationEntryTypeRef, mail.conversationEntry)).thenResolve(object())
}

o.spec("unsubscribe", function () {
function initUnsubscribeHeaders(headers: string) {
const viewModel = makeViewModelWithHeaders(headers)
const mailGroupInfo = createTestEntity(GroupInfoTypeRef, { mailAddressAliases: [], mailAddress: "ma@tuta.com" })
const mailGroupInfo = createTestEntity(GroupInfoTypeRef, {
mailAddressAliases: [],
mailAddress: "ma@tuta.com",
})
const mailboxDetail = { mailGroupInfo: mailGroupInfo } as MailboxDetail
when(mailModel.getMailboxDetailsForMail(matchers.anything())).thenResolve(mailboxDetail)
when(logins.getUserController()).thenReturn({ userGroupInfo: mailGroupInfo })
Expand Down Expand Up @@ -173,4 +186,50 @@ o.spec("MailViewerViewModel", function () {
})
})
})

o.spec("load mail details", function () {
o("load mail details successfully", async function () {
const viewModel = makeViewModelWithHeaders("")
when(mailFacade.loadMailDetailsBlob(mail)).thenResolve(mailDetails)

await viewModel.loadAll(Promise.resolve())

o(viewModel.isLoading()).deepEquals(false)
o(viewModel.getMailBody()).deepEquals("Hello World")
o(viewModel.didErrorsOccur()).deepEquals(false)
})

o("mail details NotFoundError", async function () {
const viewModel = makeViewModelWithHeaders("")
when(mailFacade.loadMailDetailsBlob(mail)).thenReject(new NotFoundError("mail details not found"))

await viewModel.loadAll(Promise.resolve())

o(viewModel.isLoading()).deepEquals(false)
o(viewModel.getMailBody()).deepEquals("")
o(viewModel.didErrorsOccur()).deepEquals(true)
})

o("changind sent mail from mail details draft to mail details blob", async function () {
const viewModel = makeViewModelWithHeaders("")
mail.mailDetailsDraft = ["draftListId", "draftId"]

const mailDetailsBlob = mail.mailDetails
mail.mailDetails = null

when(mailFacade.loadMailDetailsDraft(mail)).thenReject(new NotFoundError("mail details draft not found"))
await viewModel.loadAll(Promise.resolve())
o(viewModel.isLoading()).deepEquals(false)
o(viewModel.getMailBody()).deepEquals("")
o(viewModel.didErrorsOccur()).deepEquals(true)

mail.mailDetailsDraft = null
mail.mailDetails = mailDetailsBlob
await viewModel.loadAll(Promise.resolve())

o(viewModel.isLoading()).deepEquals(false)
o(viewModel.getMailBody()).deepEquals("Hello World")
o(viewModel.didErrorsOccur()).deepEquals(false)
})
})
})
Loading