Disallow Partial instance initializers

Co-authored-by: @paw-hub, @mpfau, @vaf-hub
tutanota#6118
This commit is contained in:
vis 2023-11-10 16:59:39 +01:00 committed by ganthern
parent af9d0e668c
commit 16a5590760
109 changed files with 1963 additions and 1414 deletions

View file

@ -66,4 +66,5 @@ export interface BlobElementEntity extends Entity, BlobElement {
_ownerGroup: null | Id
}
// FIXME ask willow about Entity
export type SomeEntity = ElementEntity | ListElementEntity | BlobElementEntity

View file

@ -20,7 +20,7 @@ export function isoDateToBirthday(birthdayIso: string): Birthday {
//return new Date(Number(newBirthday.year), Number(newBirthday.month) - 1, Number(newBirthday.day))
const birthdayInitializer: Partial<Birthday> = {}
if (birthdayIso.startsWith("--")) {
const monthAndDay = birthdayIso.substr(2).split("-")
const monthAndDay = birthdayIso.substring(2).split("-")
if (monthAndDay.length !== 2) {
throw new ParsingError("invalid birthday without year: " + birthdayIso)
@ -41,16 +41,14 @@ export function isoDateToBirthday(birthdayIso: string): Birthday {
birthdayInitializer.day = yearMonthAndDay[2]
}
const birthday = createBirthday(birthdayInitializer)
if (!isValidBirthday(birthday)) {
if (!isValidBirthday(birthdayInitializer)) {
throw new ParsingError("Invalid birthday format: " + birthdayIso)
}
return birthday
return createBirthday(birthdayInitializer)
}
export function isValidBirthday(birthday: Birthday): boolean {
export function isValidBirthday(birthday: Partial<Birthday>): birthday is Birthday {
const day = Number(birthday.day)
const month = Number(birthday.month)
const year = birthday.year ? Number(birthday.year) : null

View file

@ -15,7 +15,7 @@ import {
utf8Uint8ArrayToString,
} from "@tutao/tutanota-utils"
import { Cardinality, ValueType } from "../EntityConstants"
import type { ModelValue, SomeEntity, TypeModel } from "../EntityTypes"
import type { Entity, ModelValue, SomeEntity, TypeModel } from "../EntityTypes"
import { ElementEntity } from "../EntityTypes"
import { ProgrammingError } from "../error/ProgrammingError.js"
@ -60,9 +60,41 @@ export const POST_MULTIPLE_LIMIT = 100
*/
export type Stripped<T extends Partial<SomeEntity>> = Omit<
T,
"_id" | "_ownerGroup" | "_ownerEncSessionKey" | "_permissions" | "_errors" | "_format" | "_type" | `_finalEncrypted${string}` | `_defaultEncrypted${string}`
| "_id"
| "_area"
| "_owner"
| "_ownerGroup"
| "_ownerEncSessionKey"
| "_permissions"
| "_errors"
| "_format"
| "_type"
| `_finalEncrypted${string}`
| `_defaultEncrypted${string}`
>
type OptionalEntity<T extends Entity> = T & {
_id?: Id | IdTuple
_ownerGroup?: Id
}
export type StrippedEntity<T extends Entity> =
| Omit<
T,
| "_id"
| "_ownerGroup"
| "_ownerEncSessionKey"
| "_permissions"
| "_errors"
| "_format"
| "_type"
| "_area"
| "_owner"
| `_finalEncrypted${string}`
| `_defaultEncrypted${string}`
>
| OptionalEntity<T>
/**
* Tests if one id is bigger than another.
* For generated IDs we use base64ext which is sortable.
@ -371,7 +403,7 @@ export function removeTechnicalFields<E extends Partial<SomeEntity>>(entity: E)
* get a clone of a (partial) entity that does not contain any fields that would indicate that it was ever persisted anywhere.
* @param entity the entity to strip
*/
export function getStrippedClone<E extends SomeEntity>(entity: Partial<E>): Stripped<Partial<E>> {
export function getStrippedClone<E extends SomeEntity>(entity: StrippedEntity<E>): Stripped<E> {
const cloned = clone(entity)
removeTechnicalFields(cloned)
removeIdentityFields(cloned)

View file

@ -1,11 +1,11 @@
import {create} from "../../common/utils/EntityUtils.js"
import { create, Stripped, StrippedEntity } from "../../common/utils/EntityUtils.js"
import {TypeRef} from "@tutao/tutanota-utils"
import {typeModels} from "./TypeModels.js"
export const CustomerAccountPostingTypeRef: TypeRef<CustomerAccountPosting> = new TypeRef("accounting", "CustomerAccountPosting")
export function createCustomerAccountPosting(values: Partial<CustomerAccountPosting>): CustomerAccountPosting {
export function createCustomerAccountPosting(values: StrippedEntity<CustomerAccountPosting>): CustomerAccountPosting {
return Object.assign(create(typeModels.CustomerAccountPosting, CustomerAccountPostingTypeRef), values)
}
@ -20,7 +20,7 @@ export type CustomerAccountPosting = {
}
export const CustomerAccountReturnTypeRef: TypeRef<CustomerAccountReturn> = new TypeRef("accounting", "CustomerAccountReturn")
export function createCustomerAccountReturn(values: Partial<CustomerAccountReturn>): CustomerAccountReturn {
export function createCustomerAccountReturn(values: StrippedEntity<CustomerAccountReturn>): CustomerAccountReturn {
return Object.assign(create(typeModels.CustomerAccountReturn, CustomerAccountReturnTypeRef), values)
}

View file

@ -1,11 +1,11 @@
import {create} from "../../common/utils/EntityUtils.js"
import { create, Stripped, StrippedEntity } from "../../common/utils/EntityUtils.js"
import {TypeRef} from "@tutao/tutanota-utils"
import {typeModels} from "./TypeModels.js"
export const PersistenceResourcePostReturnTypeRef: TypeRef<PersistenceResourcePostReturn> = new TypeRef("base", "PersistenceResourcePostReturn")
export function createPersistenceResourcePostReturn(values: Partial<PersistenceResourcePostReturn>): PersistenceResourcePostReturn {
export function createPersistenceResourcePostReturn(values: StrippedEntity<PersistenceResourcePostReturn>): PersistenceResourcePostReturn {
return Object.assign(create(typeModels.PersistenceResourcePostReturn, PersistenceResourcePostReturnTypeRef), values)
}

View file

@ -1,4 +1,4 @@
import {create} from "../../common/utils/EntityUtils.js"
import { create, Stripped, StrippedEntity } from "../../common/utils/EntityUtils.js"
import {TypeRef} from "@tutao/tutanota-utils"
import {typeModels} from "./TypeModels.js"

View file

@ -1,11 +1,11 @@
import {create} from "../../common/utils/EntityUtils.js"
import { create, Stripped, StrippedEntity } from "../../common/utils/EntityUtils.js"
import {TypeRef} from "@tutao/tutanota-utils"
import {typeModels} from "./TypeModels.js"
export const ApprovalMailTypeRef: TypeRef<ApprovalMail> = new TypeRef("monitor", "ApprovalMail")
export function createApprovalMail(values: Partial<ApprovalMail>): ApprovalMail {
export function createApprovalMail(values: StrippedEntity<ApprovalMail>): ApprovalMail {
return Object.assign(create(typeModels.ApprovalMail, ApprovalMailTypeRef), values)
}
@ -24,7 +24,7 @@ export type ApprovalMail = {
}
export const CounterValueTypeRef: TypeRef<CounterValue> = new TypeRef("monitor", "CounterValue")
export function createCounterValue(values: Partial<CounterValue>): CounterValue {
export function createCounterValue(values: StrippedEntity<CounterValue>): CounterValue {
return Object.assign(create(typeModels.CounterValue, CounterValueTypeRef), values)
}
@ -37,7 +37,7 @@ export type CounterValue = {
}
export const ReadCounterDataTypeRef: TypeRef<ReadCounterData> = new TypeRef("monitor", "ReadCounterData")
export function createReadCounterData(values: Partial<ReadCounterData>): ReadCounterData {
export function createReadCounterData(values: StrippedEntity<ReadCounterData>): ReadCounterData {
return Object.assign(create(typeModels.ReadCounterData, ReadCounterDataTypeRef), values)
}
@ -51,7 +51,7 @@ export type ReadCounterData = {
}
export const ReadCounterReturnTypeRef: TypeRef<ReadCounterReturn> = new TypeRef("monitor", "ReadCounterReturn")
export function createReadCounterReturn(values: Partial<ReadCounterReturn>): ReadCounterReturn {
export function createReadCounterReturn(values: StrippedEntity<ReadCounterReturn>): ReadCounterReturn {
return Object.assign(create(typeModels.ReadCounterReturn, ReadCounterReturnTypeRef), values)
}
@ -65,7 +65,7 @@ export type ReadCounterReturn = {
}
export const WriteCounterDataTypeRef: TypeRef<WriteCounterData> = new TypeRef("monitor", "WriteCounterData")
export function createWriteCounterData(values: Partial<WriteCounterData>): WriteCounterData {
export function createWriteCounterData(values: StrippedEntity<WriteCounterData>): WriteCounterData {
return Object.assign(create(typeModels.WriteCounterData, WriteCounterDataTypeRef), values)
}

View file

@ -1,4 +1,4 @@
import {create} from "../../common/utils/EntityUtils.js"
import { create, Stripped, StrippedEntity } from "../../common/utils/EntityUtils.js"
import {TypeRef} from "@tutao/tutanota-utils"
import {typeModels} from "./TypeModels.js"
import {Blob} from '../sys/TypeRefs.js'
@ -6,7 +6,7 @@ import {BlobReferenceTokenWrapper} from '../sys/TypeRefs.js'
export const BlobAccessTokenPostInTypeRef: TypeRef<BlobAccessTokenPostIn> = new TypeRef("storage", "BlobAccessTokenPostIn")
export function createBlobAccessTokenPostIn(values: Partial<BlobAccessTokenPostIn>): BlobAccessTokenPostIn {
export function createBlobAccessTokenPostIn(values: StrippedEntity<BlobAccessTokenPostIn>): BlobAccessTokenPostIn {
return Object.assign(create(typeModels.BlobAccessTokenPostIn, BlobAccessTokenPostInTypeRef), values)
}
@ -21,7 +21,7 @@ export type BlobAccessTokenPostIn = {
}
export const BlobAccessTokenPostOutTypeRef: TypeRef<BlobAccessTokenPostOut> = new TypeRef("storage", "BlobAccessTokenPostOut")
export function createBlobAccessTokenPostOut(values: Partial<BlobAccessTokenPostOut>): BlobAccessTokenPostOut {
export function createBlobAccessTokenPostOut(values: StrippedEntity<BlobAccessTokenPostOut>): BlobAccessTokenPostOut {
return Object.assign(create(typeModels.BlobAccessTokenPostOut, BlobAccessTokenPostOutTypeRef), values)
}
@ -34,7 +34,7 @@ export type BlobAccessTokenPostOut = {
}
export const BlobArchiveRefTypeRef: TypeRef<BlobArchiveRef> = new TypeRef("storage", "BlobArchiveRef")
export function createBlobArchiveRef(values: Partial<BlobArchiveRef>): BlobArchiveRef {
export function createBlobArchiveRef(values: StrippedEntity<BlobArchiveRef>): BlobArchiveRef {
return Object.assign(create(typeModels.BlobArchiveRef, BlobArchiveRefTypeRef), values)
}
@ -50,7 +50,7 @@ export type BlobArchiveRef = {
}
export const BlobGetInTypeRef: TypeRef<BlobGetIn> = new TypeRef("storage", "BlobGetIn")
export function createBlobGetIn(values: Partial<BlobGetIn>): BlobGetIn {
export function createBlobGetIn(values: StrippedEntity<BlobGetIn>): BlobGetIn {
return Object.assign(create(typeModels.BlobGetIn, BlobGetInTypeRef), values)
}
@ -65,7 +65,7 @@ export type BlobGetIn = {
}
export const BlobIdTypeRef: TypeRef<BlobId> = new TypeRef("storage", "BlobId")
export function createBlobId(values: Partial<BlobId>): BlobId {
export function createBlobId(values: StrippedEntity<BlobId>): BlobId {
return Object.assign(create(typeModels.BlobId, BlobIdTypeRef), values)
}
@ -77,7 +77,7 @@ export type BlobId = {
}
export const BlobPostOutTypeRef: TypeRef<BlobPostOut> = new TypeRef("storage", "BlobPostOut")
export function createBlobPostOut(values: Partial<BlobPostOut>): BlobPostOut {
export function createBlobPostOut(values: StrippedEntity<BlobPostOut>): BlobPostOut {
return Object.assign(create(typeModels.BlobPostOut, BlobPostOutTypeRef), values)
}
@ -89,7 +89,7 @@ export type BlobPostOut = {
}
export const BlobReadDataTypeRef: TypeRef<BlobReadData> = new TypeRef("storage", "BlobReadData")
export function createBlobReadData(values: Partial<BlobReadData>): BlobReadData {
export function createBlobReadData(values: StrippedEntity<BlobReadData>): BlobReadData {
return Object.assign(create(typeModels.BlobReadData, BlobReadDataTypeRef), values)
}
@ -104,7 +104,7 @@ export type BlobReadData = {
}
export const BlobReferenceDeleteInTypeRef: TypeRef<BlobReferenceDeleteIn> = new TypeRef("storage", "BlobReferenceDeleteIn")
export function createBlobReferenceDeleteIn(values: Partial<BlobReferenceDeleteIn>): BlobReferenceDeleteIn {
export function createBlobReferenceDeleteIn(values: StrippedEntity<BlobReferenceDeleteIn>): BlobReferenceDeleteIn {
return Object.assign(create(typeModels.BlobReferenceDeleteIn, BlobReferenceDeleteInTypeRef), values)
}
@ -120,7 +120,7 @@ export type BlobReferenceDeleteIn = {
}
export const BlobReferencePutInTypeRef: TypeRef<BlobReferencePutIn> = new TypeRef("storage", "BlobReferencePutIn")
export function createBlobReferencePutIn(values: Partial<BlobReferencePutIn>): BlobReferencePutIn {
export function createBlobReferencePutIn(values: StrippedEntity<BlobReferencePutIn>): BlobReferencePutIn {
return Object.assign(create(typeModels.BlobReferencePutIn, BlobReferencePutInTypeRef), values)
}
@ -136,7 +136,7 @@ export type BlobReferencePutIn = {
}
export const BlobServerAccessInfoTypeRef: TypeRef<BlobServerAccessInfo> = new TypeRef("storage", "BlobServerAccessInfo")
export function createBlobServerAccessInfo(values: Partial<BlobServerAccessInfo>): BlobServerAccessInfo {
export function createBlobServerAccessInfo(values: StrippedEntity<BlobServerAccessInfo>): BlobServerAccessInfo {
return Object.assign(create(typeModels.BlobServerAccessInfo, BlobServerAccessInfoTypeRef), values)
}
@ -151,7 +151,7 @@ export type BlobServerAccessInfo = {
}
export const BlobServerUrlTypeRef: TypeRef<BlobServerUrl> = new TypeRef("storage", "BlobServerUrl")
export function createBlobServerUrl(values: Partial<BlobServerUrl>): BlobServerUrl {
export function createBlobServerUrl(values: StrippedEntity<BlobServerUrl>): BlobServerUrl {
return Object.assign(create(typeModels.BlobServerUrl, BlobServerUrlTypeRef), values)
}
@ -163,7 +163,7 @@ export type BlobServerUrl = {
}
export const BlobWriteDataTypeRef: TypeRef<BlobWriteData> = new TypeRef("storage", "BlobWriteData")
export function createBlobWriteData(values: Partial<BlobWriteData>): BlobWriteData {
export function createBlobWriteData(values: StrippedEntity<BlobWriteData>): BlobWriteData {
return Object.assign(create(typeModels.BlobWriteData, BlobWriteDataTypeRef), values)
}
@ -175,7 +175,7 @@ export type BlobWriteData = {
}
export const InstanceIdTypeRef: TypeRef<InstanceId> = new TypeRef("storage", "InstanceId")
export function createInstanceId(values: Partial<InstanceId>): InstanceId {
export function createInstanceId(values: StrippedEntity<InstanceId>): InstanceId {
return Object.assign(create(typeModels.InstanceId, InstanceIdTypeRef), values)
}

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
import {create} from "../../common/utils/EntityUtils.js"
import { create, Stripped, StrippedEntity } from "../../common/utils/EntityUtils.js"
import {TypeRef} from "@tutao/tutanota-utils"
import {typeModels} from "./TypeModels.js"
import {DateWrapper} from '../sys/TypeRefs.js'
@ -8,7 +8,7 @@ import {BlobReferenceTokenWrapper} from '../sys/TypeRefs.js'
export const AttachmentKeyDataTypeRef: TypeRef<AttachmentKeyData> = new TypeRef("tutanota", "AttachmentKeyData")
export function createAttachmentKeyData(values: Partial<AttachmentKeyData>): AttachmentKeyData {
export function createAttachmentKeyData(values: StrippedEntity<AttachmentKeyData>): AttachmentKeyData {
return Object.assign(create(typeModels.AttachmentKeyData, AttachmentKeyDataTypeRef), values)
}
@ -23,7 +23,7 @@ export type AttachmentKeyData = {
}
export const BirthdayTypeRef: TypeRef<Birthday> = new TypeRef("tutanota", "Birthday")
export function createBirthday(values: Partial<Birthday>): Birthday {
export function createBirthday(values: StrippedEntity<Birthday>): Birthday {
return Object.assign(create(typeModels.Birthday, BirthdayTypeRef), values)
}
@ -37,7 +37,7 @@ export type Birthday = {
}
export const BodyTypeRef: TypeRef<Body> = new TypeRef("tutanota", "Body")
export function createBody(values: Partial<Body>): Body {
export function createBody(values: StrippedEntity<Body>): Body {
return Object.assign(create(typeModels.Body, BodyTypeRef), values)
}
@ -50,7 +50,7 @@ export type Body = {
}
export const CalendarDeleteDataTypeRef: TypeRef<CalendarDeleteData> = new TypeRef("tutanota", "CalendarDeleteData")
export function createCalendarDeleteData(values: Partial<CalendarDeleteData>): CalendarDeleteData {
export function createCalendarDeleteData(values: StrippedEntity<CalendarDeleteData>): CalendarDeleteData {
return Object.assign(create(typeModels.CalendarDeleteData, CalendarDeleteDataTypeRef), values)
}
@ -63,7 +63,7 @@ export type CalendarDeleteData = {
}
export const CalendarEventTypeRef: TypeRef<CalendarEvent> = new TypeRef("tutanota", "CalendarEvent")
export function createCalendarEvent(values: Partial<CalendarEvent>): CalendarEvent {
export function createCalendarEvent(values: StrippedEntity<CalendarEvent>): CalendarEvent {
return Object.assign(create(typeModels.CalendarEvent, CalendarEventTypeRef), values)
}
@ -94,7 +94,7 @@ export type CalendarEvent = {
}
export const CalendarEventAttendeeTypeRef: TypeRef<CalendarEventAttendee> = new TypeRef("tutanota", "CalendarEventAttendee")
export function createCalendarEventAttendee(values: Partial<CalendarEventAttendee>): CalendarEventAttendee {
export function createCalendarEventAttendee(values: StrippedEntity<CalendarEventAttendee>): CalendarEventAttendee {
return Object.assign(create(typeModels.CalendarEventAttendee, CalendarEventAttendeeTypeRef), values)
}
@ -108,7 +108,7 @@ export type CalendarEventAttendee = {
}
export const CalendarEventIndexRefTypeRef: TypeRef<CalendarEventIndexRef> = new TypeRef("tutanota", "CalendarEventIndexRef")
export function createCalendarEventIndexRef(values: Partial<CalendarEventIndexRef>): CalendarEventIndexRef {
export function createCalendarEventIndexRef(values: StrippedEntity<CalendarEventIndexRef>): CalendarEventIndexRef {
return Object.assign(create(typeModels.CalendarEventIndexRef, CalendarEventIndexRefTypeRef), values)
}
@ -121,7 +121,7 @@ export type CalendarEventIndexRef = {
}
export const CalendarEventUidIndexTypeRef: TypeRef<CalendarEventUidIndex> = new TypeRef("tutanota", "CalendarEventUidIndex")
export function createCalendarEventUidIndex(values: Partial<CalendarEventUidIndex>): CalendarEventUidIndex {
export function createCalendarEventUidIndex(values: StrippedEntity<CalendarEventUidIndex>): CalendarEventUidIndex {
return Object.assign(create(typeModels.CalendarEventUidIndex, CalendarEventUidIndexTypeRef), values)
}
@ -138,7 +138,7 @@ export type CalendarEventUidIndex = {
}
export const CalendarEventUpdateTypeRef: TypeRef<CalendarEventUpdate> = new TypeRef("tutanota", "CalendarEventUpdate")
export function createCalendarEventUpdate(values: Partial<CalendarEventUpdate>): CalendarEventUpdate {
export function createCalendarEventUpdate(values: StrippedEntity<CalendarEventUpdate>): CalendarEventUpdate {
return Object.assign(create(typeModels.CalendarEventUpdate, CalendarEventUpdateTypeRef), values)
}
@ -157,7 +157,7 @@ export type CalendarEventUpdate = {
}
export const CalendarEventUpdateListTypeRef: TypeRef<CalendarEventUpdateList> = new TypeRef("tutanota", "CalendarEventUpdateList")
export function createCalendarEventUpdateList(values: Partial<CalendarEventUpdateList>): CalendarEventUpdateList {
export function createCalendarEventUpdateList(values: StrippedEntity<CalendarEventUpdateList>): CalendarEventUpdateList {
return Object.assign(create(typeModels.CalendarEventUpdateList, CalendarEventUpdateListTypeRef), values)
}
@ -170,7 +170,7 @@ export type CalendarEventUpdateList = {
}
export const CalendarGroupRootTypeRef: TypeRef<CalendarGroupRoot> = new TypeRef("tutanota", "CalendarGroupRoot")
export function createCalendarGroupRoot(values: Partial<CalendarGroupRoot>): CalendarGroupRoot {
export function createCalendarGroupRoot(values: StrippedEntity<CalendarGroupRoot>): CalendarGroupRoot {
return Object.assign(create(typeModels.CalendarGroupRoot, CalendarGroupRootTypeRef), values)
}
@ -190,7 +190,7 @@ export type CalendarGroupRoot = {
}
export const CalendarRepeatRuleTypeRef: TypeRef<CalendarRepeatRule> = new TypeRef("tutanota", "CalendarRepeatRule")
export function createCalendarRepeatRule(values: Partial<CalendarRepeatRule>): CalendarRepeatRule {
export function createCalendarRepeatRule(values: StrippedEntity<CalendarRepeatRule>): CalendarRepeatRule {
return Object.assign(create(typeModels.CalendarRepeatRule, CalendarRepeatRuleTypeRef), values)
}
@ -208,7 +208,7 @@ export type CalendarRepeatRule = {
}
export const ContactTypeRef: TypeRef<Contact> = new TypeRef("tutanota", "Contact")
export function createContact(values: Partial<Contact>): Contact {
export function createContact(values: StrippedEntity<Contact>): Contact {
return Object.assign(create(typeModels.Contact, ContactTypeRef), values)
}
@ -244,7 +244,7 @@ export type Contact = {
}
export const ContactAddressTypeRef: TypeRef<ContactAddress> = new TypeRef("tutanota", "ContactAddress")
export function createContactAddress(values: Partial<ContactAddress>): ContactAddress {
export function createContactAddress(values: StrippedEntity<ContactAddress>): ContactAddress {
return Object.assign(create(typeModels.ContactAddress, ContactAddressTypeRef), values)
}
@ -258,7 +258,7 @@ export type ContactAddress = {
}
export const ContactListTypeRef: TypeRef<ContactList> = new TypeRef("tutanota", "ContactList")
export function createContactList(values: Partial<ContactList>): ContactList {
export function createContactList(values: StrippedEntity<ContactList>): ContactList {
return Object.assign(create(typeModels.ContactList, ContactListTypeRef), values)
}
@ -277,7 +277,7 @@ export type ContactList = {
}
export const ContactListEntryTypeRef: TypeRef<ContactListEntry> = new TypeRef("tutanota", "ContactListEntry")
export function createContactListEntry(values: Partial<ContactListEntry>): ContactListEntry {
export function createContactListEntry(values: StrippedEntity<ContactListEntry>): ContactListEntry {
return Object.assign(create(typeModels.ContactListEntry, ContactListEntryTypeRef), values)
}
@ -294,7 +294,7 @@ export type ContactListEntry = {
}
export const ContactListGroupRootTypeRef: TypeRef<ContactListGroupRoot> = new TypeRef("tutanota", "ContactListGroupRoot")
export function createContactListGroupRoot(values: Partial<ContactListGroupRoot>): ContactListGroupRoot {
export function createContactListGroupRoot(values: StrippedEntity<ContactListGroupRoot>): ContactListGroupRoot {
return Object.assign(create(typeModels.ContactListGroupRoot, ContactListGroupRootTypeRef), values)
}
@ -312,7 +312,7 @@ export type ContactListGroupRoot = {
}
export const ContactMailAddressTypeRef: TypeRef<ContactMailAddress> = new TypeRef("tutanota", "ContactMailAddress")
export function createContactMailAddress(values: Partial<ContactMailAddress>): ContactMailAddress {
export function createContactMailAddress(values: StrippedEntity<ContactMailAddress>): ContactMailAddress {
return Object.assign(create(typeModels.ContactMailAddress, ContactMailAddressTypeRef), values)
}
@ -326,7 +326,7 @@ export type ContactMailAddress = {
}
export const ContactPhoneNumberTypeRef: TypeRef<ContactPhoneNumber> = new TypeRef("tutanota", "ContactPhoneNumber")
export function createContactPhoneNumber(values: Partial<ContactPhoneNumber>): ContactPhoneNumber {
export function createContactPhoneNumber(values: StrippedEntity<ContactPhoneNumber>): ContactPhoneNumber {
return Object.assign(create(typeModels.ContactPhoneNumber, ContactPhoneNumberTypeRef), values)
}
@ -340,7 +340,7 @@ export type ContactPhoneNumber = {
}
export const ContactSocialIdTypeRef: TypeRef<ContactSocialId> = new TypeRef("tutanota", "ContactSocialId")
export function createContactSocialId(values: Partial<ContactSocialId>): ContactSocialId {
export function createContactSocialId(values: StrippedEntity<ContactSocialId>): ContactSocialId {
return Object.assign(create(typeModels.ContactSocialId, ContactSocialIdTypeRef), values)
}
@ -354,7 +354,7 @@ export type ContactSocialId = {
}
export const ConversationEntryTypeRef: TypeRef<ConversationEntry> = new TypeRef("tutanota", "ConversationEntry")
export function createConversationEntry(values: Partial<ConversationEntry>): ConversationEntry {
export function createConversationEntry(values: StrippedEntity<ConversationEntry>): ConversationEntry {
return Object.assign(create(typeModels.ConversationEntry, ConversationEntryTypeRef), values)
}
@ -373,7 +373,7 @@ export type ConversationEntry = {
}
export const CreateExternalUserGroupDataTypeRef: TypeRef<CreateExternalUserGroupData> = new TypeRef("tutanota", "CreateExternalUserGroupData")
export function createCreateExternalUserGroupData(values: Partial<CreateExternalUserGroupData>): CreateExternalUserGroupData {
export function createCreateExternalUserGroupData(values: StrippedEntity<CreateExternalUserGroupData>): CreateExternalUserGroupData {
return Object.assign(create(typeModels.CreateExternalUserGroupData, CreateExternalUserGroupDataTypeRef), values)
}
@ -387,7 +387,7 @@ export type CreateExternalUserGroupData = {
}
export const CreateGroupPostReturnTypeRef: TypeRef<CreateGroupPostReturn> = new TypeRef("tutanota", "CreateGroupPostReturn")
export function createCreateGroupPostReturn(values: Partial<CreateGroupPostReturn>): CreateGroupPostReturn {
export function createCreateGroupPostReturn(values: StrippedEntity<CreateGroupPostReturn>): CreateGroupPostReturn {
return Object.assign(create(typeModels.CreateGroupPostReturn, CreateGroupPostReturnTypeRef), values)
}
@ -401,7 +401,7 @@ export type CreateGroupPostReturn = {
}
export const CreateLocalAdminGroupDataTypeRef: TypeRef<CreateLocalAdminGroupData> = new TypeRef("tutanota", "CreateLocalAdminGroupData")
export function createCreateLocalAdminGroupData(values: Partial<CreateLocalAdminGroupData>): CreateLocalAdminGroupData {
export function createCreateLocalAdminGroupData(values: StrippedEntity<CreateLocalAdminGroupData>): CreateLocalAdminGroupData {
return Object.assign(create(typeModels.CreateLocalAdminGroupData, CreateLocalAdminGroupDataTypeRef), values)
}
@ -415,7 +415,7 @@ export type CreateLocalAdminGroupData = {
}
export const CreateMailFolderDataTypeRef: TypeRef<CreateMailFolderData> = new TypeRef("tutanota", "CreateMailFolderData")
export function createCreateMailFolderData(values: Partial<CreateMailFolderData>): CreateMailFolderData {
export function createCreateMailFolderData(values: StrippedEntity<CreateMailFolderData>): CreateMailFolderData {
return Object.assign(create(typeModels.CreateMailFolderData, CreateMailFolderDataTypeRef), values)
}
@ -432,7 +432,7 @@ export type CreateMailFolderData = {
}
export const CreateMailFolderReturnTypeRef: TypeRef<CreateMailFolderReturn> = new TypeRef("tutanota", "CreateMailFolderReturn")
export function createCreateMailFolderReturn(values: Partial<CreateMailFolderReturn>): CreateMailFolderReturn {
export function createCreateMailFolderReturn(values: StrippedEntity<CreateMailFolderReturn>): CreateMailFolderReturn {
return Object.assign(create(typeModels.CreateMailFolderReturn, CreateMailFolderReturnTypeRef), values)
}
@ -446,7 +446,7 @@ export type CreateMailFolderReturn = {
}
export const CreateMailGroupDataTypeRef: TypeRef<CreateMailGroupData> = new TypeRef("tutanota", "CreateMailGroupData")
export function createCreateMailGroupData(values: Partial<CreateMailGroupData>): CreateMailGroupData {
export function createCreateMailGroupData(values: StrippedEntity<CreateMailGroupData>): CreateMailGroupData {
return Object.assign(create(typeModels.CreateMailGroupData, CreateMailGroupDataTypeRef), values)
}
@ -462,7 +462,7 @@ export type CreateMailGroupData = {
}
export const CustomerAccountCreateDataTypeRef: TypeRef<CustomerAccountCreateData> = new TypeRef("tutanota", "CustomerAccountCreateData")
export function createCustomerAccountCreateData(values: Partial<CustomerAccountCreateData>): CustomerAccountCreateData {
export function createCustomerAccountCreateData(values: StrippedEntity<CustomerAccountCreateData>): CustomerAccountCreateData {
return Object.assign(create(typeModels.CustomerAccountCreateData, CustomerAccountCreateDataTypeRef), values)
}
@ -487,7 +487,7 @@ export type CustomerAccountCreateData = {
}
export const DeleteGroupDataTypeRef: TypeRef<DeleteGroupData> = new TypeRef("tutanota", "DeleteGroupData")
export function createDeleteGroupData(values: Partial<DeleteGroupData>): DeleteGroupData {
export function createDeleteGroupData(values: StrippedEntity<DeleteGroupData>): DeleteGroupData {
return Object.assign(create(typeModels.DeleteGroupData, DeleteGroupDataTypeRef), values)
}
@ -501,7 +501,7 @@ export type DeleteGroupData = {
}
export const DeleteMailDataTypeRef: TypeRef<DeleteMailData> = new TypeRef("tutanota", "DeleteMailData")
export function createDeleteMailData(values: Partial<DeleteMailData>): DeleteMailData {
export function createDeleteMailData(values: StrippedEntity<DeleteMailData>): DeleteMailData {
return Object.assign(create(typeModels.DeleteMailData, DeleteMailDataTypeRef), values)
}
@ -515,7 +515,7 @@ export type DeleteMailData = {
}
export const DeleteMailFolderDataTypeRef: TypeRef<DeleteMailFolderData> = new TypeRef("tutanota", "DeleteMailFolderData")
export function createDeleteMailFolderData(values: Partial<DeleteMailFolderData>): DeleteMailFolderData {
export function createDeleteMailFolderData(values: StrippedEntity<DeleteMailFolderData>): DeleteMailFolderData {
return Object.assign(create(typeModels.DeleteMailFolderData, DeleteMailFolderDataTypeRef), values)
}
@ -529,7 +529,7 @@ export type DeleteMailFolderData = {
}
export const DraftAttachmentTypeRef: TypeRef<DraftAttachment> = new TypeRef("tutanota", "DraftAttachment")
export function createDraftAttachment(values: Partial<DraftAttachment>): DraftAttachment {
export function createDraftAttachment(values: StrippedEntity<DraftAttachment>): DraftAttachment {
return Object.assign(create(typeModels.DraftAttachment, DraftAttachmentTypeRef), values)
}
@ -544,7 +544,7 @@ export type DraftAttachment = {
}
export const DraftCreateDataTypeRef: TypeRef<DraftCreateData> = new TypeRef("tutanota", "DraftCreateData")
export function createDraftCreateData(values: Partial<DraftCreateData>): DraftCreateData {
export function createDraftCreateData(values: StrippedEntity<DraftCreateData>): DraftCreateData {
return Object.assign(create(typeModels.DraftCreateData, DraftCreateDataTypeRef), values)
}
@ -562,7 +562,7 @@ export type DraftCreateData = {
}
export const DraftCreateReturnTypeRef: TypeRef<DraftCreateReturn> = new TypeRef("tutanota", "DraftCreateReturn")
export function createDraftCreateReturn(values: Partial<DraftCreateReturn>): DraftCreateReturn {
export function createDraftCreateReturn(values: StrippedEntity<DraftCreateReturn>): DraftCreateReturn {
return Object.assign(create(typeModels.DraftCreateReturn, DraftCreateReturnTypeRef), values)
}
@ -575,7 +575,7 @@ export type DraftCreateReturn = {
}
export const DraftDataTypeRef: TypeRef<DraftData> = new TypeRef("tutanota", "DraftData")
export function createDraftData(values: Partial<DraftData>): DraftData {
export function createDraftData(values: StrippedEntity<DraftData>): DraftData {
return Object.assign(create(typeModels.DraftData, DraftDataTypeRef), values)
}
@ -600,7 +600,7 @@ export type DraftData = {
}
export const DraftRecipientTypeRef: TypeRef<DraftRecipient> = new TypeRef("tutanota", "DraftRecipient")
export function createDraftRecipient(values: Partial<DraftRecipient>): DraftRecipient {
export function createDraftRecipient(values: StrippedEntity<DraftRecipient>): DraftRecipient {
return Object.assign(create(typeModels.DraftRecipient, DraftRecipientTypeRef), values)
}
@ -613,7 +613,7 @@ export type DraftRecipient = {
}
export const DraftUpdateDataTypeRef: TypeRef<DraftUpdateData> = new TypeRef("tutanota", "DraftUpdateData")
export function createDraftUpdateData(values: Partial<DraftUpdateData>): DraftUpdateData {
export function createDraftUpdateData(values: StrippedEntity<DraftUpdateData>): DraftUpdateData {
return Object.assign(create(typeModels.DraftUpdateData, DraftUpdateDataTypeRef), values)
}
@ -628,7 +628,7 @@ export type DraftUpdateData = {
}
export const DraftUpdateReturnTypeRef: TypeRef<DraftUpdateReturn> = new TypeRef("tutanota", "DraftUpdateReturn")
export function createDraftUpdateReturn(values: Partial<DraftUpdateReturn>): DraftUpdateReturn {
export function createDraftUpdateReturn(values: StrippedEntity<DraftUpdateReturn>): DraftUpdateReturn {
return Object.assign(create(typeModels.DraftUpdateReturn, DraftUpdateReturnTypeRef), values)
}
@ -642,7 +642,7 @@ export type DraftUpdateReturn = {
}
export const EmailTemplateTypeRef: TypeRef<EmailTemplate> = new TypeRef("tutanota", "EmailTemplate")
export function createEmailTemplate(values: Partial<EmailTemplate>): EmailTemplate {
export function createEmailTemplate(values: StrippedEntity<EmailTemplate>): EmailTemplate {
return Object.assign(create(typeModels.EmailTemplate, EmailTemplateTypeRef), values)
}
@ -662,7 +662,7 @@ export type EmailTemplate = {
}
export const EmailTemplateContentTypeRef: TypeRef<EmailTemplateContent> = new TypeRef("tutanota", "EmailTemplateContent")
export function createEmailTemplateContent(values: Partial<EmailTemplateContent>): EmailTemplateContent {
export function createEmailTemplateContent(values: StrippedEntity<EmailTemplateContent>): EmailTemplateContent {
return Object.assign(create(typeModels.EmailTemplateContent, EmailTemplateContentTypeRef), values)
}
@ -675,7 +675,7 @@ export type EmailTemplateContent = {
}
export const EncryptTutanotaPropertiesDataTypeRef: TypeRef<EncryptTutanotaPropertiesData> = new TypeRef("tutanota", "EncryptTutanotaPropertiesData")
export function createEncryptTutanotaPropertiesData(values: Partial<EncryptTutanotaPropertiesData>): EncryptTutanotaPropertiesData {
export function createEncryptTutanotaPropertiesData(values: StrippedEntity<EncryptTutanotaPropertiesData>): EncryptTutanotaPropertiesData {
return Object.assign(create(typeModels.EncryptTutanotaPropertiesData, EncryptTutanotaPropertiesDataTypeRef), values)
}
@ -689,7 +689,7 @@ export type EncryptTutanotaPropertiesData = {
}
export const EncryptedMailAddressTypeRef: TypeRef<EncryptedMailAddress> = new TypeRef("tutanota", "EncryptedMailAddress")
export function createEncryptedMailAddress(values: Partial<EncryptedMailAddress>): EncryptedMailAddress {
export function createEncryptedMailAddress(values: StrippedEntity<EncryptedMailAddress>): EncryptedMailAddress {
return Object.assign(create(typeModels.EncryptedMailAddress, EncryptedMailAddressTypeRef), values)
}
@ -702,7 +702,7 @@ export type EncryptedMailAddress = {
}
export const EntropyDataTypeRef: TypeRef<EntropyData> = new TypeRef("tutanota", "EntropyData")
export function createEntropyData(values: Partial<EntropyData>): EntropyData {
export function createEntropyData(values: StrippedEntity<EntropyData>): EntropyData {
return Object.assign(create(typeModels.EntropyData, EntropyDataTypeRef), values)
}
@ -714,7 +714,7 @@ export type EntropyData = {
}
export const ExternalUserDataTypeRef: TypeRef<ExternalUserData> = new TypeRef("tutanota", "ExternalUserData")
export function createExternalUserData(values: Partial<ExternalUserData>): ExternalUserData {
export function createExternalUserData(values: StrippedEntity<ExternalUserData>): ExternalUserData {
return Object.assign(create(typeModels.ExternalUserData, ExternalUserDataTypeRef), values)
}
@ -738,7 +738,7 @@ export type ExternalUserData = {
}
export const FileTypeRef: TypeRef<File> = new TypeRef("tutanota", "File")
export function createFile(values: Partial<File>): File {
export function createFile(values: StrippedEntity<File>): File {
return Object.assign(create(typeModels.File, FileTypeRef), values)
}
@ -764,7 +764,7 @@ export type File = {
}
export const FileSystemTypeRef: TypeRef<FileSystem> = new TypeRef("tutanota", "FileSystem")
export function createFileSystem(values: Partial<FileSystem>): FileSystem {
export function createFileSystem(values: StrippedEntity<FileSystem>): FileSystem {
return Object.assign(create(typeModels.FileSystem, FileSystemTypeRef), values)
}
@ -782,7 +782,7 @@ export type FileSystem = {
}
export const GroupInvitationDeleteDataTypeRef: TypeRef<GroupInvitationDeleteData> = new TypeRef("tutanota", "GroupInvitationDeleteData")
export function createGroupInvitationDeleteData(values: Partial<GroupInvitationDeleteData>): GroupInvitationDeleteData {
export function createGroupInvitationDeleteData(values: StrippedEntity<GroupInvitationDeleteData>): GroupInvitationDeleteData {
return Object.assign(create(typeModels.GroupInvitationDeleteData, GroupInvitationDeleteDataTypeRef), values)
}
@ -795,7 +795,7 @@ export type GroupInvitationDeleteData = {
}
export const GroupInvitationPostDataTypeRef: TypeRef<GroupInvitationPostData> = new TypeRef("tutanota", "GroupInvitationPostData")
export function createGroupInvitationPostData(values: Partial<GroupInvitationPostData>): GroupInvitationPostData {
export function createGroupInvitationPostData(values: StrippedEntity<GroupInvitationPostData>): GroupInvitationPostData {
return Object.assign(create(typeModels.GroupInvitationPostData, GroupInvitationPostDataTypeRef), values)
}
@ -809,7 +809,7 @@ export type GroupInvitationPostData = {
}
export const GroupInvitationPostReturnTypeRef: TypeRef<GroupInvitationPostReturn> = new TypeRef("tutanota", "GroupInvitationPostReturn")
export function createGroupInvitationPostReturn(values: Partial<GroupInvitationPostReturn>): GroupInvitationPostReturn {
export function createGroupInvitationPostReturn(values: StrippedEntity<GroupInvitationPostReturn>): GroupInvitationPostReturn {
return Object.assign(create(typeModels.GroupInvitationPostReturn, GroupInvitationPostReturnTypeRef), values)
}
@ -824,7 +824,7 @@ export type GroupInvitationPostReturn = {
}
export const GroupInvitationPutDataTypeRef: TypeRef<GroupInvitationPutData> = new TypeRef("tutanota", "GroupInvitationPutData")
export function createGroupInvitationPutData(values: Partial<GroupInvitationPutData>): GroupInvitationPutData {
export function createGroupInvitationPutData(values: StrippedEntity<GroupInvitationPutData>): GroupInvitationPutData {
return Object.assign(create(typeModels.GroupInvitationPutData, GroupInvitationPutDataTypeRef), values)
}
@ -839,7 +839,7 @@ export type GroupInvitationPutData = {
}
export const GroupSettingsTypeRef: TypeRef<GroupSettings> = new TypeRef("tutanota", "GroupSettings")
export function createGroupSettings(values: Partial<GroupSettings>): GroupSettings {
export function createGroupSettings(values: StrippedEntity<GroupSettings>): GroupSettings {
return Object.assign(create(typeModels.GroupSettings, GroupSettingsTypeRef), values)
}
@ -854,7 +854,7 @@ export type GroupSettings = {
}
export const HeaderTypeRef: TypeRef<Header> = new TypeRef("tutanota", "Header")
export function createHeader(values: Partial<Header>): Header {
export function createHeader(values: StrippedEntity<Header>): Header {
return Object.assign(create(typeModels.Header, HeaderTypeRef), values)
}
@ -867,7 +867,7 @@ export type Header = {
}
export const ImapFolderTypeRef: TypeRef<ImapFolder> = new TypeRef("tutanota", "ImapFolder")
export function createImapFolder(values: Partial<ImapFolder>): ImapFolder {
export function createImapFolder(values: StrippedEntity<ImapFolder>): ImapFolder {
return Object.assign(create(typeModels.ImapFolder, ImapFolderTypeRef), values)
}
@ -883,7 +883,7 @@ export type ImapFolder = {
}
export const ImapSyncConfigurationTypeRef: TypeRef<ImapSyncConfiguration> = new TypeRef("tutanota", "ImapSyncConfiguration")
export function createImapSyncConfiguration(values: Partial<ImapSyncConfiguration>): ImapSyncConfiguration {
export function createImapSyncConfiguration(values: StrippedEntity<ImapSyncConfiguration>): ImapSyncConfiguration {
return Object.assign(create(typeModels.ImapSyncConfiguration, ImapSyncConfigurationTypeRef), values)
}
@ -900,7 +900,7 @@ export type ImapSyncConfiguration = {
}
export const ImapSyncStateTypeRef: TypeRef<ImapSyncState> = new TypeRef("tutanota", "ImapSyncState")
export function createImapSyncState(values: Partial<ImapSyncState>): ImapSyncState {
export function createImapSyncState(values: StrippedEntity<ImapSyncState>): ImapSyncState {
return Object.assign(create(typeModels.ImapSyncState, ImapSyncStateTypeRef), values)
}
@ -916,7 +916,7 @@ export type ImapSyncState = {
}
export const InboxRuleTypeRef: TypeRef<InboxRule> = new TypeRef("tutanota", "InboxRule")
export function createInboxRule(values: Partial<InboxRule>): InboxRule {
export function createInboxRule(values: StrippedEntity<InboxRule>): InboxRule {
return Object.assign(create(typeModels.InboxRule, InboxRuleTypeRef), values)
}
@ -931,7 +931,7 @@ export type InboxRule = {
}
export const InternalGroupDataTypeRef: TypeRef<InternalGroupData> = new TypeRef("tutanota", "InternalGroupData")
export function createInternalGroupData(values: Partial<InternalGroupData>): InternalGroupData {
export function createInternalGroupData(values: StrippedEntity<InternalGroupData>): InternalGroupData {
return Object.assign(create(typeModels.InternalGroupData, InternalGroupDataTypeRef), values)
}
@ -948,7 +948,7 @@ export type InternalGroupData = {
}
export const InternalRecipientKeyDataTypeRef: TypeRef<InternalRecipientKeyData> = new TypeRef("tutanota", "InternalRecipientKeyData")
export function createInternalRecipientKeyData(values: Partial<InternalRecipientKeyData>): InternalRecipientKeyData {
export function createInternalRecipientKeyData(values: StrippedEntity<InternalRecipientKeyData>): InternalRecipientKeyData {
return Object.assign(create(typeModels.InternalRecipientKeyData, InternalRecipientKeyDataTypeRef), values)
}
@ -962,7 +962,7 @@ export type InternalRecipientKeyData = {
}
export const KnowledgeBaseEntryTypeRef: TypeRef<KnowledgeBaseEntry> = new TypeRef("tutanota", "KnowledgeBaseEntry")
export function createKnowledgeBaseEntry(values: Partial<KnowledgeBaseEntry>): KnowledgeBaseEntry {
export function createKnowledgeBaseEntry(values: StrippedEntity<KnowledgeBaseEntry>): KnowledgeBaseEntry {
return Object.assign(create(typeModels.KnowledgeBaseEntry, KnowledgeBaseEntryTypeRef), values)
}
@ -982,7 +982,7 @@ export type KnowledgeBaseEntry = {
}
export const KnowledgeBaseEntryKeywordTypeRef: TypeRef<KnowledgeBaseEntryKeyword> = new TypeRef("tutanota", "KnowledgeBaseEntryKeyword")
export function createKnowledgeBaseEntryKeyword(values: Partial<KnowledgeBaseEntryKeyword>): KnowledgeBaseEntryKeyword {
export function createKnowledgeBaseEntryKeyword(values: StrippedEntity<KnowledgeBaseEntryKeyword>): KnowledgeBaseEntryKeyword {
return Object.assign(create(typeModels.KnowledgeBaseEntryKeyword, KnowledgeBaseEntryKeywordTypeRef), values)
}
@ -994,7 +994,7 @@ export type KnowledgeBaseEntryKeyword = {
}
export const ListUnsubscribeDataTypeRef: TypeRef<ListUnsubscribeData> = new TypeRef("tutanota", "ListUnsubscribeData")
export function createListUnsubscribeData(values: Partial<ListUnsubscribeData>): ListUnsubscribeData {
export function createListUnsubscribeData(values: StrippedEntity<ListUnsubscribeData>): ListUnsubscribeData {
return Object.assign(create(typeModels.ListUnsubscribeData, ListUnsubscribeDataTypeRef), values)
}
@ -1009,7 +1009,7 @@ export type ListUnsubscribeData = {
}
export const MailTypeRef: TypeRef<Mail> = new TypeRef("tutanota", "Mail")
export function createMail(values: Partial<Mail>): Mail {
export function createMail(values: StrippedEntity<Mail>): Mail {
return Object.assign(create(typeModels.Mail, MailTypeRef), values)
}
@ -1053,7 +1053,7 @@ export type Mail = {
}
export const MailAddressTypeRef: TypeRef<MailAddress> = new TypeRef("tutanota", "MailAddress")
export function createMailAddress(values: Partial<MailAddress>): MailAddress {
export function createMailAddress(values: StrippedEntity<MailAddress>): MailAddress {
return Object.assign(create(typeModels.MailAddress, MailAddressTypeRef), values)
}
@ -1068,7 +1068,7 @@ export type MailAddress = {
}
export const MailAddressPropertiesTypeRef: TypeRef<MailAddressProperties> = new TypeRef("tutanota", "MailAddressProperties")
export function createMailAddressProperties(values: Partial<MailAddressProperties>): MailAddressProperties {
export function createMailAddressProperties(values: StrippedEntity<MailAddressProperties>): MailAddressProperties {
return Object.assign(create(typeModels.MailAddressProperties, MailAddressPropertiesTypeRef), values)
}
@ -1081,7 +1081,7 @@ export type MailAddressProperties = {
}
export const MailBodyTypeRef: TypeRef<MailBody> = new TypeRef("tutanota", "MailBody")
export function createMailBody(values: Partial<MailBody>): MailBody {
export function createMailBody(values: StrippedEntity<MailBody>): MailBody {
return Object.assign(create(typeModels.MailBody, MailBodyTypeRef), values)
}
@ -1101,7 +1101,7 @@ export type MailBody = {
}
export const MailBoxTypeRef: TypeRef<MailBox> = new TypeRef("tutanota", "MailBox")
export function createMailBox(values: Partial<MailBox>): MailBox {
export function createMailBox(values: StrippedEntity<MailBox>): MailBox {
return Object.assign(create(typeModels.MailBox, MailBoxTypeRef), values)
}
@ -1126,7 +1126,7 @@ export type MailBox = {
}
export const MailDetailsTypeRef: TypeRef<MailDetails> = new TypeRef("tutanota", "MailDetails")
export function createMailDetails(values: Partial<MailDetails>): MailDetails {
export function createMailDetails(values: StrippedEntity<MailDetails>): MailDetails {
return Object.assign(create(typeModels.MailDetails, MailDetailsTypeRef), values)
}
@ -1144,7 +1144,7 @@ export type MailDetails = {
}
export const MailDetailsBlobTypeRef: TypeRef<MailDetailsBlob> = new TypeRef("tutanota", "MailDetailsBlob")
export function createMailDetailsBlob(values: Partial<MailDetailsBlob>): MailDetailsBlob {
export function createMailDetailsBlob(values: StrippedEntity<MailDetailsBlob>): MailDetailsBlob {
return Object.assign(create(typeModels.MailDetailsBlob, MailDetailsBlobTypeRef), values)
}
@ -1162,7 +1162,7 @@ export type MailDetailsBlob = {
}
export const MailDetailsDraftTypeRef: TypeRef<MailDetailsDraft> = new TypeRef("tutanota", "MailDetailsDraft")
export function createMailDetailsDraft(values: Partial<MailDetailsDraft>): MailDetailsDraft {
export function createMailDetailsDraft(values: StrippedEntity<MailDetailsDraft>): MailDetailsDraft {
return Object.assign(create(typeModels.MailDetailsDraft, MailDetailsDraftTypeRef), values)
}
@ -1180,7 +1180,7 @@ export type MailDetailsDraft = {
}
export const MailDetailsDraftsRefTypeRef: TypeRef<MailDetailsDraftsRef> = new TypeRef("tutanota", "MailDetailsDraftsRef")
export function createMailDetailsDraftsRef(values: Partial<MailDetailsDraftsRef>): MailDetailsDraftsRef {
export function createMailDetailsDraftsRef(values: StrippedEntity<MailDetailsDraftsRef>): MailDetailsDraftsRef {
return Object.assign(create(typeModels.MailDetailsDraftsRef, MailDetailsDraftsRefTypeRef), values)
}
@ -1193,7 +1193,7 @@ export type MailDetailsDraftsRef = {
}
export const MailFolderTypeRef: TypeRef<MailFolder> = new TypeRef("tutanota", "MailFolder")
export function createMailFolder(values: Partial<MailFolder>): MailFolder {
export function createMailFolder(values: StrippedEntity<MailFolder>): MailFolder {
return Object.assign(create(typeModels.MailFolder, MailFolderTypeRef), values)
}
@ -1215,7 +1215,7 @@ export type MailFolder = {
}
export const MailFolderRefTypeRef: TypeRef<MailFolderRef> = new TypeRef("tutanota", "MailFolderRef")
export function createMailFolderRef(values: Partial<MailFolderRef>): MailFolderRef {
export function createMailFolderRef(values: StrippedEntity<MailFolderRef>): MailFolderRef {
return Object.assign(create(typeModels.MailFolderRef, MailFolderRefTypeRef), values)
}
@ -1228,7 +1228,7 @@ export type MailFolderRef = {
}
export const MailHeadersTypeRef: TypeRef<MailHeaders> = new TypeRef("tutanota", "MailHeaders")
export function createMailHeaders(values: Partial<MailHeaders>): MailHeaders {
export function createMailHeaders(values: StrippedEntity<MailHeaders>): MailHeaders {
return Object.assign(create(typeModels.MailHeaders, MailHeadersTypeRef), values)
}
@ -1246,7 +1246,7 @@ export type MailHeaders = {
}
export const MailboxGroupRootTypeRef: TypeRef<MailboxGroupRoot> = new TypeRef("tutanota", "MailboxGroupRoot")
export function createMailboxGroupRoot(values: Partial<MailboxGroupRoot>): MailboxGroupRoot {
export function createMailboxGroupRoot(values: StrippedEntity<MailboxGroupRoot>): MailboxGroupRoot {
return Object.assign(create(typeModels.MailboxGroupRoot, MailboxGroupRootTypeRef), values)
}
@ -1268,7 +1268,7 @@ export type MailboxGroupRoot = {
}
export const MailboxPropertiesTypeRef: TypeRef<MailboxProperties> = new TypeRef("tutanota", "MailboxProperties")
export function createMailboxProperties(values: Partial<MailboxProperties>): MailboxProperties {
export function createMailboxProperties(values: StrippedEntity<MailboxProperties>): MailboxProperties {
return Object.assign(create(typeModels.MailboxProperties, MailboxPropertiesTypeRef), values)
}
@ -1287,7 +1287,7 @@ export type MailboxProperties = {
}
export const MailboxServerPropertiesTypeRef: TypeRef<MailboxServerProperties> = new TypeRef("tutanota", "MailboxServerProperties")
export function createMailboxServerProperties(values: Partial<MailboxServerProperties>): MailboxServerProperties {
export function createMailboxServerProperties(values: StrippedEntity<MailboxServerProperties>): MailboxServerProperties {
return Object.assign(create(typeModels.MailboxServerProperties, MailboxServerPropertiesTypeRef), values)
}
@ -1302,7 +1302,7 @@ export type MailboxServerProperties = {
}
export const MoveMailDataTypeRef: TypeRef<MoveMailData> = new TypeRef("tutanota", "MoveMailData")
export function createMoveMailData(values: Partial<MoveMailData>): MoveMailData {
export function createMoveMailData(values: StrippedEntity<MoveMailData>): MoveMailData {
return Object.assign(create(typeModels.MoveMailData, MoveMailDataTypeRef), values)
}
@ -1316,7 +1316,7 @@ export type MoveMailData = {
}
export const NewDraftAttachmentTypeRef: TypeRef<NewDraftAttachment> = new TypeRef("tutanota", "NewDraftAttachment")
export function createNewDraftAttachment(values: Partial<NewDraftAttachment>): NewDraftAttachment {
export function createNewDraftAttachment(values: StrippedEntity<NewDraftAttachment>): NewDraftAttachment {
return Object.assign(create(typeModels.NewDraftAttachment, NewDraftAttachmentTypeRef), values)
}
@ -1332,7 +1332,7 @@ export type NewDraftAttachment = {
}
export const NewsIdTypeRef: TypeRef<NewsId> = new TypeRef("tutanota", "NewsId")
export function createNewsId(values: Partial<NewsId>): NewsId {
export function createNewsId(values: StrippedEntity<NewsId>): NewsId {
return Object.assign(create(typeModels.NewsId, NewsIdTypeRef), values)
}
@ -1345,7 +1345,7 @@ export type NewsId = {
}
export const NewsInTypeRef: TypeRef<NewsIn> = new TypeRef("tutanota", "NewsIn")
export function createNewsIn(values: Partial<NewsIn>): NewsIn {
export function createNewsIn(values: StrippedEntity<NewsIn>): NewsIn {
return Object.assign(create(typeModels.NewsIn, NewsInTypeRef), values)
}
@ -1357,7 +1357,7 @@ export type NewsIn = {
}
export const NewsOutTypeRef: TypeRef<NewsOut> = new TypeRef("tutanota", "NewsOut")
export function createNewsOut(values: Partial<NewsOut>): NewsOut {
export function createNewsOut(values: StrippedEntity<NewsOut>): NewsOut {
return Object.assign(create(typeModels.NewsOut, NewsOutTypeRef), values)
}
@ -1370,7 +1370,7 @@ export type NewsOut = {
}
export const NotificationMailTypeRef: TypeRef<NotificationMail> = new TypeRef("tutanota", "NotificationMail")
export function createNotificationMail(values: Partial<NotificationMail>): NotificationMail {
export function createNotificationMail(values: StrippedEntity<NotificationMail>): NotificationMail {
return Object.assign(create(typeModels.NotificationMail, NotificationMailTypeRef), values)
}
@ -1386,7 +1386,7 @@ export type NotificationMail = {
}
export const OutOfOfficeNotificationTypeRef: TypeRef<OutOfOfficeNotification> = new TypeRef("tutanota", "OutOfOfficeNotification")
export function createOutOfOfficeNotification(values: Partial<OutOfOfficeNotification>): OutOfOfficeNotification {
export function createOutOfOfficeNotification(values: StrippedEntity<OutOfOfficeNotification>): OutOfOfficeNotification {
return Object.assign(create(typeModels.OutOfOfficeNotification, OutOfOfficeNotificationTypeRef), values)
}
@ -1405,7 +1405,7 @@ export type OutOfOfficeNotification = {
}
export const OutOfOfficeNotificationMessageTypeRef: TypeRef<OutOfOfficeNotificationMessage> = new TypeRef("tutanota", "OutOfOfficeNotificationMessage")
export function createOutOfOfficeNotificationMessage(values: Partial<OutOfOfficeNotificationMessage>): OutOfOfficeNotificationMessage {
export function createOutOfOfficeNotificationMessage(values: StrippedEntity<OutOfOfficeNotificationMessage>): OutOfOfficeNotificationMessage {
return Object.assign(create(typeModels.OutOfOfficeNotificationMessage, OutOfOfficeNotificationMessageTypeRef), values)
}
@ -1419,7 +1419,7 @@ export type OutOfOfficeNotificationMessage = {
}
export const OutOfOfficeNotificationRecipientListTypeRef: TypeRef<OutOfOfficeNotificationRecipientList> = new TypeRef("tutanota", "OutOfOfficeNotificationRecipientList")
export function createOutOfOfficeNotificationRecipientList(values: Partial<OutOfOfficeNotificationRecipientList>): OutOfOfficeNotificationRecipientList {
export function createOutOfOfficeNotificationRecipientList(values: StrippedEntity<OutOfOfficeNotificationRecipientList>): OutOfOfficeNotificationRecipientList {
return Object.assign(create(typeModels.OutOfOfficeNotificationRecipientList, OutOfOfficeNotificationRecipientListTypeRef), values)
}
@ -1432,7 +1432,7 @@ export type OutOfOfficeNotificationRecipientList = {
}
export const PasswordAutoAuthenticationReturnTypeRef: TypeRef<PasswordAutoAuthenticationReturn> = new TypeRef("tutanota", "PasswordAutoAuthenticationReturn")
export function createPasswordAutoAuthenticationReturn(values: Partial<PasswordAutoAuthenticationReturn>): PasswordAutoAuthenticationReturn {
export function createPasswordAutoAuthenticationReturn(values: StrippedEntity<PasswordAutoAuthenticationReturn>): PasswordAutoAuthenticationReturn {
return Object.assign(create(typeModels.PasswordAutoAuthenticationReturn, PasswordAutoAuthenticationReturnTypeRef), values)
}
@ -1443,7 +1443,7 @@ export type PasswordAutoAuthenticationReturn = {
}
export const PasswordChannelPhoneNumberTypeRef: TypeRef<PasswordChannelPhoneNumber> = new TypeRef("tutanota", "PasswordChannelPhoneNumber")
export function createPasswordChannelPhoneNumber(values: Partial<PasswordChannelPhoneNumber>): PasswordChannelPhoneNumber {
export function createPasswordChannelPhoneNumber(values: StrippedEntity<PasswordChannelPhoneNumber>): PasswordChannelPhoneNumber {
return Object.assign(create(typeModels.PasswordChannelPhoneNumber, PasswordChannelPhoneNumberTypeRef), values)
}
@ -1455,7 +1455,7 @@ export type PasswordChannelPhoneNumber = {
}
export const PasswordChannelReturnTypeRef: TypeRef<PasswordChannelReturn> = new TypeRef("tutanota", "PasswordChannelReturn")
export function createPasswordChannelReturn(values: Partial<PasswordChannelReturn>): PasswordChannelReturn {
export function createPasswordChannelReturn(values: StrippedEntity<PasswordChannelReturn>): PasswordChannelReturn {
return Object.assign(create(typeModels.PasswordChannelReturn, PasswordChannelReturnTypeRef), values)
}
@ -1468,7 +1468,7 @@ export type PasswordChannelReturn = {
}
export const PasswordMessagingDataTypeRef: TypeRef<PasswordMessagingData> = new TypeRef("tutanota", "PasswordMessagingData")
export function createPasswordMessagingData(values: Partial<PasswordMessagingData>): PasswordMessagingData {
export function createPasswordMessagingData(values: StrippedEntity<PasswordMessagingData>): PasswordMessagingData {
return Object.assign(create(typeModels.PasswordMessagingData, PasswordMessagingDataTypeRef), values)
}
@ -1482,7 +1482,7 @@ export type PasswordMessagingData = {
}
export const PasswordMessagingReturnTypeRef: TypeRef<PasswordMessagingReturn> = new TypeRef("tutanota", "PasswordMessagingReturn")
export function createPasswordMessagingReturn(values: Partial<PasswordMessagingReturn>): PasswordMessagingReturn {
export function createPasswordMessagingReturn(values: StrippedEntity<PasswordMessagingReturn>): PasswordMessagingReturn {
return Object.assign(create(typeModels.PasswordMessagingReturn, PasswordMessagingReturnTypeRef), values)
}
@ -1494,7 +1494,7 @@ export type PasswordMessagingReturn = {
}
export const PasswordRetrievalDataTypeRef: TypeRef<PasswordRetrievalData> = new TypeRef("tutanota", "PasswordRetrievalData")
export function createPasswordRetrievalData(values: Partial<PasswordRetrievalData>): PasswordRetrievalData {
export function createPasswordRetrievalData(values: StrippedEntity<PasswordRetrievalData>): PasswordRetrievalData {
return Object.assign(create(typeModels.PasswordRetrievalData, PasswordRetrievalDataTypeRef), values)
}
@ -1506,7 +1506,7 @@ export type PasswordRetrievalData = {
}
export const PasswordRetrievalReturnTypeRef: TypeRef<PasswordRetrievalReturn> = new TypeRef("tutanota", "PasswordRetrievalReturn")
export function createPasswordRetrievalReturn(values: Partial<PasswordRetrievalReturn>): PasswordRetrievalReturn {
export function createPasswordRetrievalReturn(values: StrippedEntity<PasswordRetrievalReturn>): PasswordRetrievalReturn {
return Object.assign(create(typeModels.PasswordRetrievalReturn, PasswordRetrievalReturnTypeRef), values)
}
@ -1518,7 +1518,7 @@ export type PasswordRetrievalReturn = {
}
export const PhishingMarkerWebsocketDataTypeRef: TypeRef<PhishingMarkerWebsocketData> = new TypeRef("tutanota", "PhishingMarkerWebsocketData")
export function createPhishingMarkerWebsocketData(values: Partial<PhishingMarkerWebsocketData>): PhishingMarkerWebsocketData {
export function createPhishingMarkerWebsocketData(values: StrippedEntity<PhishingMarkerWebsocketData>): PhishingMarkerWebsocketData {
return Object.assign(create(typeModels.PhishingMarkerWebsocketData, PhishingMarkerWebsocketDataTypeRef), values)
}
@ -1532,7 +1532,7 @@ export type PhishingMarkerWebsocketData = {
}
export const PhotosRefTypeRef: TypeRef<PhotosRef> = new TypeRef("tutanota", "PhotosRef")
export function createPhotosRef(values: Partial<PhotosRef>): PhotosRef {
export function createPhotosRef(values: StrippedEntity<PhotosRef>): PhotosRef {
return Object.assign(create(typeModels.PhotosRef, PhotosRefTypeRef), values)
}
@ -1545,7 +1545,7 @@ export type PhotosRef = {
}
export const ReceiveInfoServiceDataTypeRef: TypeRef<ReceiveInfoServiceData> = new TypeRef("tutanota", "ReceiveInfoServiceData")
export function createReceiveInfoServiceData(values: Partial<ReceiveInfoServiceData>): ReceiveInfoServiceData {
export function createReceiveInfoServiceData(values: StrippedEntity<ReceiveInfoServiceData>): ReceiveInfoServiceData {
return Object.assign(create(typeModels.ReceiveInfoServiceData, ReceiveInfoServiceDataTypeRef), values)
}
@ -1557,7 +1557,7 @@ export type ReceiveInfoServiceData = {
}
export const RecipientsTypeRef: TypeRef<Recipients> = new TypeRef("tutanota", "Recipients")
export function createRecipients(values: Partial<Recipients>): Recipients {
export function createRecipients(values: StrippedEntity<Recipients>): Recipients {
return Object.assign(create(typeModels.Recipients, RecipientsTypeRef), values)
}
@ -1572,7 +1572,7 @@ export type Recipients = {
}
export const RemoteImapSyncInfoTypeRef: TypeRef<RemoteImapSyncInfo> = new TypeRef("tutanota", "RemoteImapSyncInfo")
export function createRemoteImapSyncInfo(values: Partial<RemoteImapSyncInfo>): RemoteImapSyncInfo {
export function createRemoteImapSyncInfo(values: StrippedEntity<RemoteImapSyncInfo>): RemoteImapSyncInfo {
return Object.assign(create(typeModels.RemoteImapSyncInfo, RemoteImapSyncInfoTypeRef), values)
}
@ -1589,7 +1589,7 @@ export type RemoteImapSyncInfo = {
}
export const ReportMailPostDataTypeRef: TypeRef<ReportMailPostData> = new TypeRef("tutanota", "ReportMailPostData")
export function createReportMailPostData(values: Partial<ReportMailPostData>): ReportMailPostData {
export function createReportMailPostData(values: StrippedEntity<ReportMailPostData>): ReportMailPostData {
return Object.assign(create(typeModels.ReportMailPostData, ReportMailPostDataTypeRef), values)
}
@ -1604,7 +1604,7 @@ export type ReportMailPostData = {
}
export const ReportedMailFieldMarkerTypeRef: TypeRef<ReportedMailFieldMarker> = new TypeRef("tutanota", "ReportedMailFieldMarker")
export function createReportedMailFieldMarker(values: Partial<ReportedMailFieldMarker>): ReportedMailFieldMarker {
export function createReportedMailFieldMarker(values: StrippedEntity<ReportedMailFieldMarker>): ReportedMailFieldMarker {
return Object.assign(create(typeModels.ReportedMailFieldMarker, ReportedMailFieldMarkerTypeRef), values)
}
@ -1617,7 +1617,7 @@ export type ReportedMailFieldMarker = {
}
export const SecureExternalRecipientKeyDataTypeRef: TypeRef<SecureExternalRecipientKeyData> = new TypeRef("tutanota", "SecureExternalRecipientKeyData")
export function createSecureExternalRecipientKeyData(values: Partial<SecureExternalRecipientKeyData>): SecureExternalRecipientKeyData {
export function createSecureExternalRecipientKeyData(values: StrippedEntity<SecureExternalRecipientKeyData>): SecureExternalRecipientKeyData {
return Object.assign(create(typeModels.SecureExternalRecipientKeyData, SecureExternalRecipientKeyDataTypeRef), values)
}
@ -1639,7 +1639,7 @@ export type SecureExternalRecipientKeyData = {
}
export const SendDraftDataTypeRef: TypeRef<SendDraftData> = new TypeRef("tutanota", "SendDraftData")
export function createSendDraftData(values: Partial<SendDraftData>): SendDraftData {
export function createSendDraftData(values: StrippedEntity<SendDraftData>): SendDraftData {
return Object.assign(create(typeModels.SendDraftData, SendDraftDataTypeRef), values)
}
@ -1661,7 +1661,7 @@ export type SendDraftData = {
}
export const SendDraftReturnTypeRef: TypeRef<SendDraftReturn> = new TypeRef("tutanota", "SendDraftReturn")
export function createSendDraftReturn(values: Partial<SendDraftReturn>): SendDraftReturn {
export function createSendDraftReturn(values: StrippedEntity<SendDraftReturn>): SendDraftReturn {
return Object.assign(create(typeModels.SendDraftReturn, SendDraftReturnTypeRef), values)
}
@ -1677,7 +1677,7 @@ export type SendDraftReturn = {
}
export const SharedGroupDataTypeRef: TypeRef<SharedGroupData> = new TypeRef("tutanota", "SharedGroupData")
export function createSharedGroupData(values: Partial<SharedGroupData>): SharedGroupData {
export function createSharedGroupData(values: StrippedEntity<SharedGroupData>): SharedGroupData {
return Object.assign(create(typeModels.SharedGroupData, SharedGroupDataTypeRef), values)
}
@ -1696,7 +1696,7 @@ export type SharedGroupData = {
}
export const SpamResultsTypeRef: TypeRef<SpamResults> = new TypeRef("tutanota", "SpamResults")
export function createSpamResults(values: Partial<SpamResults>): SpamResults {
export function createSpamResults(values: StrippedEntity<SpamResults>): SpamResults {
return Object.assign(create(typeModels.SpamResults, SpamResultsTypeRef), values)
}
@ -1709,7 +1709,7 @@ export type SpamResults = {
}
export const SubfilesTypeRef: TypeRef<Subfiles> = new TypeRef("tutanota", "Subfiles")
export function createSubfiles(values: Partial<Subfiles>): Subfiles {
export function createSubfiles(values: StrippedEntity<Subfiles>): Subfiles {
return Object.assign(create(typeModels.Subfiles, SubfilesTypeRef), values)
}
@ -1722,7 +1722,7 @@ export type Subfiles = {
}
export const TemplateGroupRootTypeRef: TypeRef<TemplateGroupRoot> = new TypeRef("tutanota", "TemplateGroupRoot")
export function createTemplateGroupRoot(values: Partial<TemplateGroupRoot>): TemplateGroupRoot {
export function createTemplateGroupRoot(values: StrippedEntity<TemplateGroupRoot>): TemplateGroupRoot {
return Object.assign(create(typeModels.TemplateGroupRoot, TemplateGroupRootTypeRef), values)
}
@ -1741,7 +1741,7 @@ export type TemplateGroupRoot = {
}
export const TutanotaPropertiesTypeRef: TypeRef<TutanotaProperties> = new TypeRef("tutanota", "TutanotaProperties")
export function createTutanotaProperties(values: Partial<TutanotaProperties>): TutanotaProperties {
export function createTutanotaProperties(values: StrippedEntity<TutanotaProperties>): TutanotaProperties {
return Object.assign(create(typeModels.TutanotaProperties, TutanotaPropertiesTypeRef), values)
}
@ -1770,7 +1770,7 @@ export type TutanotaProperties = {
}
export const UpdateMailFolderDataTypeRef: TypeRef<UpdateMailFolderData> = new TypeRef("tutanota", "UpdateMailFolderData")
export function createUpdateMailFolderData(values: Partial<UpdateMailFolderData>): UpdateMailFolderData {
export function createUpdateMailFolderData(values: StrippedEntity<UpdateMailFolderData>): UpdateMailFolderData {
return Object.assign(create(typeModels.UpdateMailFolderData, UpdateMailFolderDataTypeRef), values)
}
@ -1784,7 +1784,7 @@ export type UpdateMailFolderData = {
}
export const UserAccountCreateDataTypeRef: TypeRef<UserAccountCreateData> = new TypeRef("tutanota", "UserAccountCreateData")
export function createUserAccountCreateData(values: Partial<UserAccountCreateData>): UserAccountCreateData {
export function createUserAccountCreateData(values: StrippedEntity<UserAccountCreateData>): UserAccountCreateData {
return Object.assign(create(typeModels.UserAccountCreateData, UserAccountCreateDataTypeRef), values)
}
@ -1799,7 +1799,7 @@ export type UserAccountCreateData = {
}
export const UserAccountUserDataTypeRef: TypeRef<UserAccountUserData> = new TypeRef("tutanota", "UserAccountUserData")
export function createUserAccountUserData(values: Partial<UserAccountUserData>): UserAccountUserData {
export function createUserAccountUserData(values: StrippedEntity<UserAccountUserData>): UserAccountUserData {
return Object.assign(create(typeModels.UserAccountUserData, UserAccountUserDataTypeRef), values)
}
@ -1832,7 +1832,7 @@ export type UserAccountUserData = {
}
export const UserAreaGroupDataTypeRef: TypeRef<UserAreaGroupData> = new TypeRef("tutanota", "UserAreaGroupData")
export function createUserAreaGroupData(values: Partial<UserAreaGroupData>): UserAreaGroupData {
export function createUserAreaGroupData(values: StrippedEntity<UserAreaGroupData>): UserAreaGroupData {
return Object.assign(create(typeModels.UserAreaGroupData, UserAreaGroupDataTypeRef), values)
}
@ -1850,7 +1850,7 @@ export type UserAreaGroupData = {
}
export const UserAreaGroupDeleteDataTypeRef: TypeRef<UserAreaGroupDeleteData> = new TypeRef("tutanota", "UserAreaGroupDeleteData")
export function createUserAreaGroupDeleteData(values: Partial<UserAreaGroupDeleteData>): UserAreaGroupDeleteData {
export function createUserAreaGroupDeleteData(values: StrippedEntity<UserAreaGroupDeleteData>): UserAreaGroupDeleteData {
return Object.assign(create(typeModels.UserAreaGroupDeleteData, UserAreaGroupDeleteDataTypeRef), values)
}
@ -1863,7 +1863,7 @@ export type UserAreaGroupDeleteData = {
}
export const UserAreaGroupPostDataTypeRef: TypeRef<UserAreaGroupPostData> = new TypeRef("tutanota", "UserAreaGroupPostData")
export function createUserAreaGroupPostData(values: Partial<UserAreaGroupPostData>): UserAreaGroupPostData {
export function createUserAreaGroupPostData(values: StrippedEntity<UserAreaGroupPostData>): UserAreaGroupPostData {
return Object.assign(create(typeModels.UserAreaGroupPostData, UserAreaGroupPostDataTypeRef), values)
}
@ -1876,7 +1876,7 @@ export type UserAreaGroupPostData = {
}
export const UserSettingsGroupRootTypeRef: TypeRef<UserSettingsGroupRoot> = new TypeRef("tutanota", "UserSettingsGroupRoot")
export function createUserSettingsGroupRoot(values: Partial<UserSettingsGroupRoot>): UserSettingsGroupRoot {
export function createUserSettingsGroupRoot(values: StrippedEntity<UserSettingsGroupRoot>): UserSettingsGroupRoot {
return Object.assign(create(typeModels.UserSettingsGroupRoot, UserSettingsGroupRootTypeRef), values)
}

View file

@ -1,11 +1,11 @@
import {create} from "../../common/utils/EntityUtils.js"
import { create, Stripped, StrippedEntity } from "../../common/utils/EntityUtils.js"
import {TypeRef} from "@tutao/tutanota-utils"
import {typeModels} from "./TypeModels.js"
export const UsageTestAssignmentTypeRef: TypeRef<UsageTestAssignment> = new TypeRef("usage", "UsageTestAssignment")
export function createUsageTestAssignment(values: Partial<UsageTestAssignment>): UsageTestAssignment {
export function createUsageTestAssignment(values: StrippedEntity<UsageTestAssignment>): UsageTestAssignment {
return Object.assign(create(typeModels.UsageTestAssignment, UsageTestAssignmentTypeRef), values)
}
@ -22,7 +22,7 @@ export type UsageTestAssignment = {
}
export const UsageTestAssignmentInTypeRef: TypeRef<UsageTestAssignmentIn> = new TypeRef("usage", "UsageTestAssignmentIn")
export function createUsageTestAssignmentIn(values: Partial<UsageTestAssignmentIn>): UsageTestAssignmentIn {
export function createUsageTestAssignmentIn(values: StrippedEntity<UsageTestAssignmentIn>): UsageTestAssignmentIn {
return Object.assign(create(typeModels.UsageTestAssignmentIn, UsageTestAssignmentInTypeRef), values)
}
@ -34,7 +34,7 @@ export type UsageTestAssignmentIn = {
}
export const UsageTestAssignmentOutTypeRef: TypeRef<UsageTestAssignmentOut> = new TypeRef("usage", "UsageTestAssignmentOut")
export function createUsageTestAssignmentOut(values: Partial<UsageTestAssignmentOut>): UsageTestAssignmentOut {
export function createUsageTestAssignmentOut(values: StrippedEntity<UsageTestAssignmentOut>): UsageTestAssignmentOut {
return Object.assign(create(typeModels.UsageTestAssignmentOut, UsageTestAssignmentOutTypeRef), values)
}
@ -48,7 +48,7 @@ export type UsageTestAssignmentOut = {
}
export const UsageTestMetricConfigTypeRef: TypeRef<UsageTestMetricConfig> = new TypeRef("usage", "UsageTestMetricConfig")
export function createUsageTestMetricConfig(values: Partial<UsageTestMetricConfig>): UsageTestMetricConfig {
export function createUsageTestMetricConfig(values: StrippedEntity<UsageTestMetricConfig>): UsageTestMetricConfig {
return Object.assign(create(typeModels.UsageTestMetricConfig, UsageTestMetricConfigTypeRef), values)
}
@ -63,7 +63,7 @@ export type UsageTestMetricConfig = {
}
export const UsageTestMetricConfigValueTypeRef: TypeRef<UsageTestMetricConfigValue> = new TypeRef("usage", "UsageTestMetricConfigValue")
export function createUsageTestMetricConfigValue(values: Partial<UsageTestMetricConfigValue>): UsageTestMetricConfigValue {
export function createUsageTestMetricConfigValue(values: StrippedEntity<UsageTestMetricConfigValue>): UsageTestMetricConfigValue {
return Object.assign(create(typeModels.UsageTestMetricConfigValue, UsageTestMetricConfigValueTypeRef), values)
}
@ -76,7 +76,7 @@ export type UsageTestMetricConfigValue = {
}
export const UsageTestMetricDataTypeRef: TypeRef<UsageTestMetricData> = new TypeRef("usage", "UsageTestMetricData")
export function createUsageTestMetricData(values: Partial<UsageTestMetricData>): UsageTestMetricData {
export function createUsageTestMetricData(values: StrippedEntity<UsageTestMetricData>): UsageTestMetricData {
return Object.assign(create(typeModels.UsageTestMetricData, UsageTestMetricDataTypeRef), values)
}
@ -89,7 +89,7 @@ export type UsageTestMetricData = {
}
export const UsageTestParticipationInTypeRef: TypeRef<UsageTestParticipationIn> = new TypeRef("usage", "UsageTestParticipationIn")
export function createUsageTestParticipationIn(values: Partial<UsageTestParticipationIn>): UsageTestParticipationIn {
export function createUsageTestParticipationIn(values: StrippedEntity<UsageTestParticipationIn>): UsageTestParticipationIn {
return Object.assign(create(typeModels.UsageTestParticipationIn, UsageTestParticipationInTypeRef), values)
}
@ -105,7 +105,7 @@ export type UsageTestParticipationIn = {
}
export const UsageTestStageTypeRef: TypeRef<UsageTestStage> = new TypeRef("usage", "UsageTestStage")
export function createUsageTestStage(values: Partial<UsageTestStage>): UsageTestStage {
export function createUsageTestStage(values: StrippedEntity<UsageTestStage>): UsageTestStage {
return Object.assign(create(typeModels.UsageTestStage, UsageTestStageTypeRef), values)
}

View file

@ -382,12 +382,19 @@ export async function initUserController({ user, userGroupInfo, sessionId, acces
const entityClient = locator.entityClient
const [props, userSettingsGroupRoot] = await Promise.all([
entityClient.loadRoot(TutanotaPropertiesTypeRef, user.userGroup.group),
entityClient
.load(UserSettingsGroupRootTypeRef, user.userGroup.group)
.catch(
entityClient.load(UserSettingsGroupRootTypeRef, user.userGroup.group).catch(
ofClass(NotFoundError, () =>
entityClient
.setup(null, createUserSettingsGroupRoot({ _ownerGroup: user.userGroup.group }))
.setup(
null,
createUserSettingsGroupRoot({
_ownerGroup: user.userGroup.group,
startOfTheWeek: "0",
timeFormat: "0",
groupSettings: [],
usageDataOptedIn: null,
}),
)
.then(() => entityClient.load(UserSettingsGroupRootTypeRef, user.userGroup.group)),
),
),

View file

@ -63,6 +63,7 @@ export class BlobAccessTokenFacade {
write: createBlobWriteData({
archiveOwnerGroup: ownerGroupId,
}),
read: null,
})
const { blobAccessInfo } = await this.serviceExecutor.post(BlobAccessTokenService, tokenRequest)
return blobAccessInfo
@ -104,6 +105,7 @@ export class BlobAccessTokenFacade {
instanceListId,
instanceIds,
}),
write: null,
})
const { blobAccessInfo } = await this.serviceExecutor.post(BlobAccessTokenService, tokenRequest)
return blobAccessInfo
@ -130,7 +132,9 @@ export class BlobAccessTokenFacade {
read: createBlobReadData({
archiveId,
instanceIds: [],
instanceListId: null,
}),
write: null,
})
const { blobAccessInfo } = await this.serviceExecutor.post(BlobAccessTokenService, tokenRequest)
return blobAccessInfo

View file

@ -215,9 +215,13 @@ export class LoginFacade {
// the verifier is always sent as url parameter, so it must be url encoded
const authVerifier = createAuthVerifierAsBase64Url(userPassphraseKey)
const createSessionData = createCreateSessionData({
mailAddress: mailAddress.toLowerCase().trim(),
clientIdentifier,
accessKey: null,
authToken: null,
authVerifier,
clientIdentifier,
mailAddress: mailAddress.toLowerCase().trim(),
recoverCodeVerifier: null,
user: null,
})
let accessKey: Aes128Key | null = null
@ -342,10 +346,13 @@ export class LoginFacade {
const authVerifier = createAuthVerifierAsBase64Url(userPassphraseKey)
const authToken = base64ToBase64Url(uint8ArrayToBase64(sha256Hash(salt)))
const sessionData = createCreateSessionData({
user: userId,
accessKey: null,
authToken,
clientIdentifier,
authVerifier,
clientIdentifier,
mailAddress: null,
recoverCodeVerifier: null,
user: userId,
})
let accessKey: Aes128Key | null = null
@ -795,11 +802,13 @@ export class LoginFacade {
const pwEncUserGroupKey = encryptKey(newUserPassphraseKey, this.userFacade.getUserGroupKey())
const authVerifier = createAuthVerifier(newUserPassphraseKey)
const service = createChangePasswordData({
code: null,
kdfVersion: newKdfType,
oldVerifier: currentAuthVerifier,
pwEncUserGroupKey: pwEncUserGroupKey,
recoverCodeVerifier: null,
salt: salt,
verifier: authVerifier,
pwEncUserGroupKey: pwEncUserGroupKey,
})
await this.serviceExecutor.post(ChangePasswordService, service)
@ -811,9 +820,10 @@ export class LoginFacade {
const passwordKey = await this.deriveUserPassphraseKey(asKdfType(this.userFacade.getLoggedInUser().kdfVersion), password, userSalt)
const deleteCustomerData = createDeleteCustomerData({
authVerifier: createAuthVerifier(passwordKey),
reason: reason,
takeoverMailAddress: null,
undelete: false,
customer: neverNull(neverNull(this.userFacade.getLoggedInUser()).customer),
reason: reason,
})
if (takeover !== "") {
@ -830,9 +840,13 @@ export class LoginFacade {
const recoverCodeVerifier = createAuthVerifier(recoverCodeKey)
const recoverCodeVerifierBase64 = base64ToBase64Url(uint8ArrayToBase64(recoverCodeVerifier))
const sessionData = createCreateSessionData({
mailAddress: mailAddress.toLowerCase().trim(),
accessKey: null,
authToken: null,
authVerifier: null,
clientIdentifier: clientIdentifier,
mailAddress: mailAddress.toLowerCase().trim(),
recoverCodeVerifier: recoverCodeVerifierBase64,
user: null,
})
// we need a separate entity rest client because to avoid caching of the user instance which is updated on password change. the web socket is not connected because we
// don't do a normal login and therefore we would not get any user update events. we can not use permanentLogin=false with initSession because caching would be enabled
@ -878,8 +892,10 @@ export class LoginFacade {
const pwEncUserGroupKey = encryptKey(userPassphraseKey, groupKey)
const newPasswordVerifier = createAuthVerifier(userPassphraseKey)
const postData = createChangePasswordData({
salt: salt,
code: null,
kdfVersion: newKdfType,
oldVerifier: null,
salt: salt,
pwEncUserGroupKey: pwEncUserGroupKey,
verifier: newPasswordVerifier,
recoverCodeVerifier: recoverCodeVerifier,

View file

@ -250,6 +250,7 @@ export class BlobFacade {
const getData = createBlobGetIn({
archiveId,
blobId,
blobIds: [],
})
const BlobGetInTypeModel = await resolveTypeReference(BlobGetInTypeRef)
const literalGetData = await this.instanceMapper.encryptAndMapToLiteral(BlobGetInTypeModel, getData, null)
@ -276,6 +277,7 @@ export class BlobFacade {
const getData = createBlobGetIn({
archiveId,
blobId,
blobIds: [],
})
const BlobGetInTypeModel = await resolveTypeReference(BlobGetInTypeRef)
const literalGetData = await this.instanceMapper.encryptAndMapToLiteral(BlobGetInTypeModel, getData, null)

View file

@ -40,7 +40,10 @@ export class BookingFacade {
* @return Resolves to PriceServiceReturn or an exception if the loading failed.
*/
getCurrentPrice(): Promise<PriceServiceReturn> {
const serviceData = createPriceServiceData({})
const serviceData = createPriceServiceData({
date: null,
priceRequest: null,
})
return this.serviceExecutor.get(PriceService, serviceData)
}

View file

@ -23,6 +23,7 @@ export class CounterFacade {
const counterData = createReadCounterData({
counterType,
rowName: customerId,
columnName: null,
})
const counterReturn = await this.serviceExecutor.get(CounterService, counterData)
return counterReturn.counterValues

View file

@ -83,6 +83,7 @@ export class CustomerFacade {
addDomain(domainName: string): Promise<CustomDomainReturn> {
const data = createCustomDomainData({
domain: domainName.trim().toLowerCase(),
catchAllMailGroup: null,
})
return this.serviceExecutor.post(CustomDomainService, data)
}
@ -90,6 +91,7 @@ export class CustomerFacade {
async removeDomain(domainName: string): Promise<void> {
const data = createCustomDomainData({
domain: domainName.trim().toLowerCase(),
catchAllMailGroup: null,
})
await this.serviceExecutor.delete(CustomDomainService, data)
}
@ -115,6 +117,8 @@ export class CustomerFacade {
const data = createBrandingDomainData({
domain: domainName,
systemAdminPubEncSessionKey: systemAdminPubEncAccountingInfoSessionKey,
sessionEncPemPrivateKey: null,
sessionEncPemCertificateChain: null,
})
if (existingBrandingDomain) {
await this.serviceExecutor.put(BrandingDomainService, data)
@ -303,6 +307,7 @@ export class CustomerFacade {
adminEncAccountingInfoSessionKey: encryptKey(adminGroupKey, accountingInfoSessionKey),
systemAdminPubEncAccountingInfoSessionKey,
adminEncCustomerServerPropertiesSessionKey: encryptKey(adminGroupKey, customerServerPropertiesSessionKey),
userEncAccountGroupKey: new Uint8Array(0),
})
await this.serviceExecutor.post(CustomerAccountService, data)
return recoverData.hexCode
@ -398,6 +403,7 @@ export class CustomerFacade {
async downloadInvoice(invoiceNumber: string): Promise<DataFile> {
const data = createPdfInvoiceServiceData({
invoiceNumber,
invoice: null,
})
return this.serviceExecutor.get(PdfInvoiceService, data).then((returnData) => {
return {

View file

@ -61,6 +61,7 @@ export class GiftCardFacade {
createGiftCardRedeemData({
giftCardInfo: id,
keyHash: sha256Hash(bitArrayToUint8Array(base64ToKey(key))),
countryCode: "",
}),
{
sessionKey: base64ToKey(key),

View file

@ -112,7 +112,10 @@ export class MailAddressFacade {
const mailboxProperties = await this.getOrCreateMailboxProperties(mailGroupId, viaUser)
let mailAddressProperty = mailboxProperties.mailAddressProperties.find((p) => p.mailAddress === mailAddress)
if (mailAddressProperty == null) {
mailAddressProperty = createMailAddressProperties({ mailAddress })
mailAddressProperty = createMailAddressProperties({
mailAddress,
senderName: "",
})
mailboxProperties.mailAddressProperties.push(mailAddressProperty)
}
mailAddressProperty.senderName = senderName
@ -181,12 +184,13 @@ export class MailAddressFacade {
}
private async createMailboxProperties(mailboxGroupRoot: MailboxGroupRoot, groupKey: Aes128Key): Promise<Id> {
// Using non-caching entityClient because we are not a member of the user's mail group and we won't receive updates for it
const _ownerGroup = mailboxGroupRoot._ownerGroup
const mailboxProperties = createMailboxProperties({
_ownerGroup: mailboxGroupRoot._ownerGroup,
...(_ownerGroup != null ? { _ownerGroup } : null), // only set it if it is not null
reportMovedMails: "",
mailAddressProperties: [],
})
// Using non-caching entityClient because we are not a member of the user's mail group and we won't receive updates for it
return this.nonCachingEntityClient.setup(null, mailboxProperties, undefined, { ownerKey: groupKey }).catch(
ofClass(PreconditionFailedError, (e) => {
// in admin case it is much harder to run into it because we use non-caching entityClient but it is still possible

View file

@ -260,6 +260,8 @@ export class MailFacade {
bccRecipients: bccRecipients.map(recipientToDraftRecipient),
replyTos: replyTos.map(recipientToEncryptedMailAddress),
addedAttachments: await this._createAddedAttachments(attachments, [], senderMailGroupId, mailGroupKey),
bodyText: "",
removedAttachments: [],
}),
})
const createDraftReturn = await this.serviceExecutor.post(DraftService, service, { sessionKey: sk })
@ -318,6 +320,7 @@ export class MailFacade {
replyTos: replyTos,
removedAttachments: this._getRemovedAttachments(attachments, currentAttachments),
addedAttachments: await this._createAddedAttachments(attachments, currentAttachments, senderMailGroupId, mailGroupKey),
bodyText: "",
}),
})
this.deferredDraftId = draft._id
@ -417,6 +420,7 @@ export class MailFacade {
const attachment = createDraftAttachment({
existingFile: getLetId(providedFile),
ownerEncFileSessionKey: encryptKey(mailGroupKey, assertNotNull(fileSessionKey, "filesessionkey was not resolved")),
newFile: null,
})
return attachment
})
@ -449,6 +453,7 @@ export class MailFacade {
encCid: providedFile.cid == null ? null : encryptString(fileSessionKey, providedFile.cid),
}),
ownerEncFileSessionKey: encryptKey(mailGroupKey, fileSessionKey),
existingFile: null,
})
}
@ -458,6 +463,14 @@ export class MailFacade {
const sendDraftData = createSendDraftData({
language: language,
mail: draft._id,
mailSessionKey: null,
attachmentKeyData: [],
calendarMethod: false,
internalRecipientKeyData: [],
plaintext: false,
bucketEncMailSessionKey: null,
senderNameUnencrypted: null,
secureExternalRecipientKeyData: [],
})
const attachments = await this.getAttachmentIds(draft)
@ -466,6 +479,8 @@ export class MailFacade {
const fileSessionKey = assertNotNull(await this.crypto.resolveSessionKeyForInstance(file), "fileSessionKey was null")
const data = createAttachmentKeyData({
file: fileId,
fileSessionKey: null,
bucketEncFileSessionKey: null,
})
if (draft.confidential) {
@ -650,6 +665,8 @@ export class MailFacade {
salt: salt,
saltHash: sha256Hash(salt),
pwEncCommunicationKey: encryptKey(passwordKey, externalGroupKeys.externalUserGroupKey),
autoTransmitPassword: null,
passwordChannelPhoneNumbers: [],
})
service.secureExternalRecipientKeyData.push(data)
} else {
@ -742,6 +759,7 @@ export class MailFacade {
externalUserEncTutanotaPropertiesSessionKey: encryptKey(externalUserGroupKey, tutanotaPropertiesSessionKey),
externalMailEncMailBoxSessionKey: encryptKey(externalMailGroupKey, mailboxSessionKey),
userGroupData: userGroupData,
kdfVersion: "0",
})
return this.serviceExecutor.post(ExternalUserService, d).then(() => {
return {
@ -824,6 +842,7 @@ export class MailFacade {
async clearFolder(folderId: IdTuple) {
const deleteMailData = createDeleteMailData({
folder: folderId,
mails: [],
})
await this.serviceExecutor.delete(MailService, deleteMailData)
}

View file

@ -180,6 +180,7 @@ function attendeesLine(event: CalendarEvent): string {
organizer,
createCalendarEventAttendee({
address: organizer,
status: "0",
}),
)
}

View file

@ -251,12 +251,14 @@ export class DefaultDateProvider implements DateProvider {
}
export function createRepeatRuleWithValues(frequency: RepeatPeriod, interval: number, timeZone: string = getTimeZone()): CalendarRepeatRule {
const rule = createCalendarRepeatRule({
return createCalendarRepeatRule({
timeZone: timeZone,
frequency: frequency,
interval: String(interval),
endValue: null,
endType: "0",
excludedDates: [],
})
return rule
}
export function colorForBg(color: string): string {

View file

@ -65,6 +65,8 @@ export class CalendarEventAlarmModel {
return createAlarmInfo({
alarmIdentifier: generateEventElementId(this.dateProvider.now()),
trigger: serializeAlarmInterval(alarmInterval),
// @ts-ignore
calendarRef: null, // FIXME
})
}

View file

@ -95,7 +95,7 @@ import { CalendarEventWhenModel } from "./CalendarEventWhenModel.js"
import { CalendarEventWhoModel } from "./CalendarEventWhoModel.js"
import { CalendarEventAlarmModel } from "./CalendarEventAlarmModel.js"
import { SanitizedTextViewModel } from "../../../misc/SanitizedTextViewModel.js"
import { getStrippedClone, Stripped } from "../../../api/common/utils/EntityUtils.js"
import { getStrippedClone, Stripped, StrippedEntity } from "../../../api/common/utils/EntityUtils.js"
import { UserController } from "../../../api/main/UserController.js"
import { CalendarNotificationModel, CalendarNotificationSendModels } from "./CalendarNotificationModel.js"
import { CalendarEventApplyStrategies, CalendarEventModelStrategy } from "./CalendarEventModelStrategy.js"
@ -186,7 +186,6 @@ export async function makeCalendarEventModel(
initialValues = index.progenitor
}
}
const cleanInitialValues = cleanupInitialValuesForEditing(initialValues)
const user = logins.getUserController().user
const [alarms, calendars] = await Promise.all([
@ -231,18 +230,27 @@ export async function makeCalendarEventModel(
uid == null ? [] : (await calendarModel.getEventsByUid(uid))?.alteredInstances.map((i) => i.recurrenceId) ?? []
const notificationModel = new CalendarNotificationModel(notificationSender, logins)
const applyStrategies = new CalendarEventApplyStrategies(calendarModel, logins, notificationModel, recurrenceIds, showProgress, zone)
const initialOrDefaultValues = Object.assign(makeEmptyCalendarEvent(), initialValues)
const cleanInitialValues = cleanupInitialValuesForEditing(initialOrDefaultValues)
const progenitor = () => calendarModel.resolveCalendarEventProgenitor(cleanInitialValues)
const strategy = await selectStrategy(makeEditModels, applyStrategies, operation, progenitor, createCalendarEvent(initialValues), cleanInitialValues)
const strategy = await selectStrategy(
makeEditModels,
applyStrategies,
operation,
progenitor,
createCalendarEvent(initialOrDefaultValues),
cleanInitialValues,
)
return strategy && new CalendarEventModel(strategy, eventType, operation, logins.getUserController(), notificationSender, entityClient, calendars)
}
async function selectStrategy(
makeEditModels: (i: CalendarEvent) => CalendarEventEditModels,
makeEditModels: (i: StrippedEntity<CalendarEvent>) => CalendarEventEditModels,
applyStrategies: CalendarEventApplyStrategies,
operation: CalendarOperation,
resolveProgenitor: () => Promise<CalendarEvent | null>,
existingInstanceIdentity: CalendarEvent,
cleanInitialValues: CalendarEvent,
cleanInitialValues: StrippedEntity<CalendarEvent>,
): Promise<CalendarEventModelStrategy | null> {
let editModels: CalendarEventEditModels
let apply: () => Promise<void>
@ -540,11 +548,27 @@ export function assembleEditResultAndAssignFromExisting(existingEvent: CalendarE
* @param identity sequence (default "0") and recurrenceId (default null) are optional, but the uid must be specified.
*/
export function assignEventIdentity(values: CalendarEventValues, identity: Require<"uid", Partial<CalendarEventIdentity>>): CalendarEvent {
return createCalendarEvent({
...values,
return Object.assign(
createCalendarEvent({
sequence: "0",
...identity,
})
organizer: null,
attendees: [],
description: "",
repeatRule: null,
location: "",
summary: "",
endTime: new Date(),
uid: null,
startTime: new Date(),
recurrenceId: null,
invitedConfidentially: null,
// @ts-ignore
alarmInfos: null, // FIXME
hashedUid: null,
}),
values,
identity,
)
}
async function resolveAlarmsForEvent(alarms: CalendarEvent["alarmInfos"], calendarModel: CalendarModel, user: User): Promise<Array<AlarmInterval>> {
@ -552,7 +576,27 @@ async function resolveAlarmsForEvent(alarms: CalendarEvent["alarmInfos"], calend
return alarmInfos.map(({ alarmInfo }) => parseAlarmInterval(alarmInfo.trigger))
}
function cleanupInitialValuesForEditing(initialValues: Partial<CalendarEvent>): CalendarEvent {
function makeEmptyCalendarEvent(): StrippedEntity<CalendarEvent> {
return {
// @ts-ignore
alarmInfos: null, // FIXME
invitedConfidentially: null,
hashedUid: null,
uid: null,
recurrenceId: null,
endTime: new Date(),
summary: "",
startTime: new Date(),
location: "",
repeatRule: null,
description: "",
attendees: [],
organizer: null,
sequence: "",
}
}
function cleanupInitialValuesForEditing(initialValues: StrippedEntity<CalendarEvent>): CalendarEvent {
// the event we got passed may already have some technical fields assigned, so we remove them.
const stripped = getStrippedClone<CalendarEvent>(initialValues)
const result = createCalendarEvent(stripped)

View file

@ -266,6 +266,7 @@ export class CalendarEventWhenModel {
endValue: "1",
frequency: RepeatPeriod.DAILY,
excludedDates: [],
timeZone: "",
})
this.repeatRule.frequency = repeatPeriod
}
@ -468,7 +469,20 @@ export class CalendarEventWhenModel {
get result(): CalendarEventWhenModelResult {
// we got a stripped repeat rule, so we re-create a fresh one with all fields but overwrite it with our values.
const repeatRule: RepeatRule | null = this.repeatRule ? { ...createRepeatRule({}), ...this.repeatRule, timeZone: this.zone } : null
const repeatRule: RepeatRule | null = this.repeatRule
? {
...createRepeatRule({
timeZone: "",
excludedDates: [],
endType: "0",
endValue: null,
interval: "0",
frequency: "0",
}),
...this.repeatRule,
timeZone: this.zone,
}
: null
this.deleteExcludedDatesIfNecessary(repeatRule)
const { startTime, endTime } = this.getTimes()
return { startTime, endTime, repeatRule }

View file

@ -56,6 +56,10 @@ export function makeInvitationCalendarFile(event: CalendarEvent, method: Calenda
name: `${method.toLowerCase()}-${date.getFullYear()}${date.getMonth() + 1}${date.getDate()}.ics`,
mimeType: CALENDAR_MIME_TYPE,
size: String(data.byteLength),
cid: null,
blobs: [],
parent: null,
subFiles: null,
})
return convertToDataFile(tmpFile, data)
}

View file

@ -219,6 +219,10 @@ function exportCalendarEvents(
name: calendarName === "" ? "export.ics" : calendarName + "-export.ics",
mimeType: CALENDAR_MIME_TYPE,
size: String(data.byteLength),
subFiles: null,
parent: null,
cid: null,
blobs: [],
})
return locator.fileController.saveDataFile(convertToDataFile(tmpFile, data))
}

View file

@ -271,6 +271,9 @@ function parseAlarm(alarmObject: ICalObject, event: CalendarEvent): AlarmInfo |
return alarmInterval != null
? createAlarmInfo({
trigger: serializeAlarmInterval(alarmInterval),
alarmIdentifier: "",
// @ts-ignore
calendarRef: null, // FIXME
})
: null
}
@ -350,6 +353,8 @@ export function parseRrule(rruleProp: Property, tzId: string | null): RepeatRule
endType: endType,
interval: String(interval),
frequency: frequency,
excludedDates: [],
timeZone: "",
})
if (typeof tzId === "string") {
@ -628,6 +633,9 @@ export function parseCalendarEvents(icalObject: ICalObject, zone: string): Parse
sequence,
attendees,
organizer,
hashedUid: null,
invitedConfidentially: null,
alarmInfos: [],
}) as Require<"uid", CalendarEvent>
const alarms: AlarmInfo[] = []

View file

@ -193,6 +193,7 @@ export class CalendarModel {
const newGroupSettings = createGroupSettings({
group: group._id,
color: color,
name: null,
})
userSettingsGroupRoot.groupSettings.push(newGroupSettings)
await this.entityClient.update(userSettingsGroupRoot)

View file

@ -305,6 +305,7 @@ function prepareAttendees(attendees: Array<CalendarEventAttendee>, organizer: En
createCalendarEventAttendee({
address: createEncryptedMailAddress({
address: organizer.address,
name: "",
}),
status: CalendarAttendeeStatus.ADDED, // We don't know whether the organizer will be attending or not in this case
}),

View file

@ -76,7 +76,27 @@ export class ContactEditor {
listId?: Id,
private readonly newContactIdReceiver: ((contactId: Id) => unknown) | null = null,
) {
this.contact = contact ? clone(contact) : createContact({})
this.contact = contact
? clone(contact)
: createContact({
mailAddresses: [],
title: null,
socialIds: [],
role: "",
presharedPassword: null,
photo: null,
phoneNumbers: [],
oldBirthdayDate: null,
nickname: null,
lastName: "",
firstName: "",
company: "",
comment: "",
birthdayIso: null,
addresses: [],
autoTransmitPassword: "",
oldBirthdayAggregate: null,
})
this.isNewContact = contact?._id == null
if (this.isNewContact && listId == null) {

View file

@ -1,8 +1,8 @@
import { convertToDataFile } from "../api/common/DataFile"
import type { Contact, ContactAddress, ContactMailAddress, ContactPhoneNumber, ContactSocialId } from "../api/entities/tutanota/TypeRefs.js"
import { createFile } from "../api/entities/tutanota/TypeRefs.js"
import { stringToUtf8Uint8Array } from "@tutao/tutanota-utils"
import { ContactAddressType, ContactPhoneNumberType } from "../api/common/TutanotaConstants"
import type { Contact, ContactSocialId, ContactPhoneNumber, ContactAddress, ContactMailAddress } from "../api/entities/tutanota/TypeRefs.js"
import { assertMainOrNode } from "../api/common/Env"
import { locator } from "../api/main/MainLocator"
import { getSocialUrl } from "./model/ContactUtils.js"
@ -16,10 +16,13 @@ export function exportContacts(contacts: Contact[]): Promise<void> {
name: "vCard3.0.vcf",
mimeType: "vCard/rfc2426",
size: String(data.byteLength),
blobs: [],
cid: null,
parent: null,
subFiles: null,
})
return locator.fileController.saveDataFile(convertToDataFile(tmpFile, data))
}
/**
* Converts an array of contacts to a vCard 3.0 compatible string.
*

View file

@ -165,6 +165,7 @@ export function vCardListToContacts(vCardList: string[], ownerGroupId: Id): Cont
bDayDetails = createBirthday({
month: tagValue.substring(2, 4),
day: tagValue.substring(4, 6),
year: null,
})
} else if (tagValue.match(/\d{4}-\d{2}-\d{2}/g)) {
let bDay = tagValue.substring(0, indexOfT !== -1 ? indexOfT : tagValue.length).split("-")
@ -310,6 +311,10 @@ export function vCardListToContacts(vCardList: string[], ownerGroupId: Id): Cont
mailAddresses,
phoneNumbers,
socialIds,
presharedPassword: null,
photo: null,
oldBirthdayDate: null,
oldBirthdayAggregate: null,
})
}

View file

@ -63,6 +63,22 @@ export class ContactListEntryViewer implements Component<ContactListEntryViewerA
address: attrs.entry.emailAddress,
}),
],
oldBirthdayAggregate: null,
autoTransmitPassword: "",
addresses: [],
birthdayIso: null,
comment: "",
company: "",
firstName: "",
lastName: "",
nickname: null,
oldBirthdayDate: null,
phoneNumbers: [],
photo: null,
role: "",
presharedPassword: null,
socialIds: [],
title: null,
})
attrs.contactCreate(newContact)
},

View file

@ -5,7 +5,7 @@ import { AppHeaderAttrs, Header } from "../../gui/Header.js"
import { Button, ButtonColor, ButtonType } from "../../gui/base/Button.js"
import { ContactEditor } from "../ContactEditor"
import type { Contact } from "../../api/entities/tutanota/TypeRefs.js"
import { ContactTypeRef, createGroupSettings } from "../../api/entities/tutanota/TypeRefs.js"
import { ContactTypeRef } from "../../api/entities/tutanota/TypeRefs.js"
import { ContactListView } from "./ContactListView"
import { lang } from "../../misc/LanguageViewModel"
import { assertNotNull, clear, getFirstOrThrow, noOp, ofClass } from "@tutao/tutanota-utils"
@ -657,11 +657,6 @@ export class ContactView extends BaseTopLevelView implements TopLevelView<Contac
if (existingGroupSettings) {
existingGroupSettings.name = newName
} else {
const newGroupSettings = createGroupSettings({
group: contactListInfo.group._id,
name: newName,
})
}
locator.entityClient.update(userSettingsGroupRoot)

View file

@ -937,6 +937,9 @@ export class SendMailModel {
_id: [listId, stringToCustomId(this.senderAddress)],
_ownerGroup: this.user().user.userGroup.group,
text: `Subject: ${this.getSubject()}<br>${body}`,
date: null,
range: null,
customer: null,
})
return this.entity.setup(listId, m).catch(ofClass(NotAuthorizedError, (e) => console.log("not authorized for approval message")))
}

View file

@ -518,7 +518,9 @@ export class MailModel {
.setup(
null,
createMailboxProperties({
_ownerGroup: mailboxGroupRoot._ownerGroup,
_ownerGroup: mailboxGroupRoot._ownerGroup ?? "",
reportMovedMails: "0",
mailAddressProperties: [],
}),
)
.catch(

View file

@ -1,5 +1,10 @@
import type { Contact, EncryptedMailAddress, InboxRule, Mail, MailFolder, TutanotaProperties } from "../../api/entities/tutanota/TypeRefs.js"
import {
Birthday,
ContactAddress,
ContactMailAddress,
ContactPhoneNumber,
ContactSocialId,
createContact,
createContactMailAddress,
createEncryptedMailAddress,
@ -72,6 +77,20 @@ export function createNewContact(user: User, mailAddress: string, name: string):
customTypeName: "",
}),
],
autoTransmitPassword: "",
birthdayIso: null,
comment: "",
company: "",
nickname: null,
oldBirthdayDate: null,
presharedPassword: null,
role: "",
title: null,
addresses: [],
oldBirthdayAggregate: null,
phoneNumbers: [],
photo: null,
socialIds: [],
})
return contact
}

View file

@ -6,7 +6,7 @@ import { FeatureType, InboxRuleType, Keys, MailFolderType, SpamRuleFieldType, Sp
import type { Mail } from "../../api/entities/tutanota/TypeRefs.js"
import { lang } from "../../misc/LanguageViewModel"
import { assertMainOrNode } from "../../api/common/Env"
import { assertNonNull, assertNotNull, defer, DeferredObject, noOp, ofClass } from "@tutao/tutanota-utils"
import { assertNonNull, assertNotNull, defer, DeferredObject, noOp, ofClass, stringToUtf8Uint8Array, uint8ArrayToBase64 } from "@tutao/tutanota-utils"
import { createNewContact, getExistingRuleForType, isTutanotaTeamMail } from "../model/MailUtils"
import { IconMessageBox } from "../../gui/base/ColumnEmptyMessageBox"
import type { Shortcut } from "../../misc/KeyManager"
@ -671,12 +671,14 @@ export class MailViewer implements Component<MailViewerAttrs> {
break
}
import("../../settings/AddSpamRuleDialog").then(({ showAddSpamRuleDialog }) => {
Promise.all([import("../../settings/AddSpamRuleDialog"), import("@tutao/tutanota-crypto")]).then(([{ showAddSpamRuleDialog }, { sha256Hash }]) => {
const value = address.trim().toLowerCase()
showAddSpamRuleDialog(
createEmailSenderListElement({
value: address.trim().toLowerCase(),
value,
type: spamRuleType,
field: spamRuleField,
hashedValue: uint8ArrayToBase64(sha256Hash(stringToUtf8Uint8Array(value))),
}),
)
})

View file

@ -936,6 +936,7 @@ export class MailViewerViewModel {
const recipient = createMailAddress({
address: neverNull(userGroupInfo.mailAddress),
name: userGroupInfo.name,
contact: null,
})
let newReplyTos

View file

@ -150,6 +150,8 @@ export class SecondFactorAuthDialog {
type: SecondFactorType.totp,
session: this.authData.sessionId,
otpCode: this.otpState.code.replace(/ /g, ""),
u2f: null,
webauthn: null,
})
try {
@ -190,6 +192,8 @@ export class SecondFactorAuthDialog {
type: SecondFactorType.webauthn,
session: sessionId,
webauthn: responseData,
u2f: null,
otpCode: null,
})
await this.loginFacade.authenticateWithSecondFactor(authData, apiBaseUrl)
} catch (e) {

View file

@ -137,6 +137,9 @@ export class SecondFactorHandler {
createSecondFactorAuthData({
session: session._id,
type: null, // Marker for confirming another session
otpCode: null,
u2f: null,
webauthn: null,
}),
)

View file

@ -115,6 +115,9 @@ export class NativePushServiceApp {
pushServiceType: pushServiceType,
identifier,
language: lang.code,
disabled: false,
lastUsageTime: new Date(),
lastNotificationDate: null,
})
const id = await this.entityClient.setup(list, pushIdentifier)
return this.entityClient.load(PushIdentifierTypeRef, [list, id])

View file

@ -111,6 +111,8 @@ export function createInboxRuleTemplate(ruleType: string | null, value: string |
return createInboxRule({
type: ruleType || InboxRuleType.FROM_EQUALS,
value: getCleanedValue(neverNull(ruleType), value || ""),
// @ts-ignore
targetFolder: null, // FIXME
})
}

View file

@ -54,7 +54,12 @@ export class EditOutOfOfficeNotificationDialogModel {
if (!outOfOfficeNotification) {
this.startDate(getStartOfDay(new Date()))
this.outOfOfficeNotification = createOutOfOfficeNotification({})
this.outOfOfficeNotification = createOutOfOfficeNotification({
notifications: [],
enabled: false,
endDate: null,
startDate: null,
})
} else {
this.outOfOfficeNotification = outOfOfficeNotification
this.enabled(outOfOfficeNotification.enabled)

View file

@ -403,6 +403,7 @@ export class GlobalSettingsViewer implements UpdatableSettingsViewer {
value: domainPart ? domainPart : "",
type: SpamRuleType.WHITELIST,
field: SpamRuleFieldType.FROM,
hashedValue: "",
}),
)
},

View file

@ -210,6 +210,9 @@ export class IdentifierListViewer {
identifier: assertNotNull(getCleanedMailAddress(mailAddress)),
language: lang.code,
pushServiceType: PushServiceType.EMAIL,
lastUsageTime: new Date(),
lastNotificationDate: null,
disabled: false,
})
let p = locator.entityClient.setup(assertNotNull(user.pushIdentifierList).list, pushIdentifier)

View file

@ -26,7 +26,7 @@ export class KnowledgeBaseEditorModel {
this.keywords = stream(entry ? keywordsToString(entry.keywords) : "")
this._entityClient = entityClient
this._templateGroupRoot = templateGroupInstances
this.entry = entry ? clone(entry) : createKnowledgeBaseEntry({})
this.entry = entry ? clone(entry) : createKnowledgeBaseEntry({ description: "", title: "", keywords: [] })
this._descriptionProvider = null
this.availableTemplates = new LazyLoaded(() => {
return this._entityClient.loadAll(EmailTemplateTypeRef, this._templateGroupRoot.templates)

View file

@ -23,7 +23,7 @@ export class TemplateEditorModel {
_contentProvider: (() => string) | null
constructor(template: EmailTemplate | null, templateGroupRoot: TemplateGroupRoot, entityClient: EntityClient) {
this.template = template ? clone(template) : createEmailTemplate({})
this.template = template ? clone(template) : createEmailTemplate({ tag: "", title: "", contents: [] })
this.title = stream("")
this.tag = stream("")
const contents = this.template.contents

View file

@ -29,7 +29,9 @@ export function showAddDomainWizard(domain: string, customerInfo: CustomerInfo,
const domainData: AddDomainData = {
domain: stream(domain),
customerInfo: customerInfo,
expectedVerificationRecord: createDnsRecord({}),
// will be filled oncreate by the page
// not actually spf, but the type TXT only matters here
expectedVerificationRecord: createDnsRecord({ subdomain: null, type: DnsRecordType.DNS_RECORD_TYPE_TXT_SPF, value: "" }),
editAliasFormAttrs: {
model: mailAddressTableModel,
expanded: mailAddressTableExpanded,
@ -37,10 +39,6 @@ export function showAddDomainWizard(domain: string, customerInfo: CustomerInfo,
},
domainStatus: new DomainDnsStatus(domain),
}
domainData.expectedVerificationRecord.type = DnsRecordType.DNS_RECORD_TYPE_TXT_SPF // not actually spf, but the type TXT only matters here
domainData.expectedVerificationRecord.subdomain = null
domainData.expectedVerificationRecord.value = "" // will be filled oncreate by the page
const wizardPages = [
wizardPageWrapper(EnterDomainPage, new EnterDomainPageAttrs(domainData)),

View file

@ -70,7 +70,7 @@ export class SecondFactorEditModel {
width: 150,
content: url,
padding: 2,
// We don't want <xml> around the content, we actually enforce <svg> namespace and we want it to be parsed as such.
// We don't want <xml> around the content, we actually enforce <svg> namespace, and we want it to be parsed as such.
xmlDeclaration: false,
})
totpQRCodeSvg = htmlSanitizer.sanitizeSVG(qrcodeGenerator.svg()).html
@ -181,17 +181,19 @@ export class SecondFactorEditModel {
}
this.updateViewCallback()
const sf = createSecondFactor({
_ownerGroup: this.user._ownerGroup,
name: this.name,
})
if (this.selectedType === SecondFactorType.u2f) {
throw new ProgrammingError(`invalid factor type: ${this.selectedType}`)
} else {
sf.type = this.selectedType
}
const sf = createSecondFactor({
_ownerGroup: this.user._ownerGroup!,
name: this.name,
type: this.selectedType,
otpSecret: null,
u2f: null,
})
if (this.selectedType === SecondFactorType.webauthn) {
if (this.verificationStatus !== VerificationStatus.Success) {
throw new UserError("unrecognizedU2fDevice_msg")

View file

@ -18,10 +18,11 @@ export class OwnMailAddressNameChanger implements MailAddressNameChanger {
const mailboxProperties = await this.mailModel.getMailboxProperties(mailboxDetails.mailboxGroupRoot)
let aliasConfig = mailboxProperties.mailAddressProperties.find((p) => p.mailAddress === address)
if (aliasConfig == null) {
aliasConfig = createMailAddressProperties({ mailAddress: address })
aliasConfig = createMailAddressProperties({ mailAddress: address, senderName: name })
mailboxProperties.mailAddressProperties.push(aliasConfig)
}
} else {
aliasConfig.senderName = name
}
await this.entityClient.update(mailboxProperties)
return this.collectMap(mailboxProperties)
}

View file

@ -1,8 +1,7 @@
import m, { Children, Component } from "mithril"
import { px, size } from "../../gui/size"
import { Button, ButtonType } from "../../gui/base/Button.js"
import { createMail } from "../../api/entities/tutanota/TypeRefs.js"
import { createMailAddress } from "../../api/entities/tutanota/TypeRefs.js"
import { createMail, createMailAddress } from "../../api/entities/tutanota/TypeRefs.js"
import { MailRow } from "../../mail/view/MailRow"
import { noOp } from "@tutao/tutanota-utils"
import { IconButton } from "../../gui/base/IconButton.js"
@ -78,6 +77,7 @@ export class CustomColorEditorPreview implements Component {
sender: createMailAddress({
address: "m.mustermann@example.com",
name: "Max Mustermann",
contact: null,
}),
receivedDate: new Date(),
subject: "Mail 1",
@ -86,11 +86,33 @@ export class CustomColorEditorPreview implements Component {
confidential: true,
attachments: [],
state: "2",
mailDetails: null,
body: null,
authStatus: null,
method: "0",
bccRecipients: [],
bucketKey: null,
ccRecipients: [],
headers: null,
// @ts-ignore
conversationEntry: null, // FIXME
differentEnvelopeSender: null,
firstRecipient: null,
listUnsubscribe: false,
mailDetailsDraft: null,
movedTime: null,
phishingStatus: "0",
recipientCount: "0",
replyTos: [],
restrictions: null,
sentDate: null,
toRecipients: [],
})
const mail2 = createMail({
sender: createMailAddress({
address: "m.mustermann@example.com",
name: "Max Mustermann",
contact: null,
}),
receivedDate: new Date(),
subject: "Mail 2",
@ -99,6 +121,14 @@ export class CustomColorEditorPreview implements Component {
confidential: false,
attachments: [],
state: "2",
authStatus: null,
sentDate: null,
phishingStatus: "0",
mailDetailsDraft: null,
// @ts-ignore
conversationEntry: null, // FIXME
headers: null,
mailDetails: null,
})
return m(
".rel",

View file

@ -355,7 +355,7 @@ export class PaymentViewer implements UpdatableSettingsViewer {
return showProgressDialog(
"pleaseWait_msg",
locator.serviceExecutor
.put(DebitService, createDebitServicePutData({}))
.put(DebitService, createDebitServicePutData({ invoice: null }))
.catch(ofClass(LockedError, () => "operationStillActive_msg" as TranslationKey))
.catch(
ofClass(PreconditionFailedError, (error) => {

View file

@ -258,6 +258,8 @@ async function cancelSubscription(dialog: Dialog, currentPlanInfo: CurrentPlanIn
date: Const.CURRENT_DATE,
customer: customer._id,
specialPriceUserSingle: null,
referralCode: null,
plan: PlanType.Free,
})
try {
await showProgressDialog(

View file

@ -37,9 +37,11 @@ export class UpgradeConfirmSubscriptionPage implements WizardPageN<UpgradeSubscr
private upgrade(data: UpgradeSubscriptionData) {
const serviceData = createSwitchAccountTypePostIn({
accountType: AccountType.PAID,
customer: null,
plan: data.type,
date: Const.CURRENT_DATE,
referralCode: data.referralCode,
specialPriceUserSingle: null,
})
showProgressDialog(
"pleaseWait_msg",

View file

@ -129,7 +129,7 @@ export function createTestEntity<T extends Entity>(typeRef: TypeRef<T>, values?:
const typeModel = resolveTypeReference(typeRef as TypeRef<any>)
const entity = create(typeModel, typeRef)
if (values) {
return { ...entity, values }
return Object.assign(entity, values)
} else {
return entity
}

View file

@ -1,12 +1,13 @@
import o from "@tutao/otest"
import { createBirthday } from "../../../../../src/api/entities/tutanota/TypeRefs.js"
import { BirthdayTypeRef, createBirthday } from "../../../../../src/api/entities/tutanota/TypeRefs.js"
import { birthdayToIsoDate, isoDateToBirthday } from "../../../../../src/api/common/utils/BirthdayUtils.js"
import { ParsingError } from "../../../../../src/api/common/error/ParsingError.js"
import { TutanotaError } from "../../../../../src/api/common/error/TutanotaError.js"
import { createTestEntity } from "../../../TestUtils.js"
o.spec("BirthdayUtilsTest", function () {
o("birthdayToIsoDate", function () {
const bday = createBirthday({
const bday = createTestEntity(BirthdayTypeRef, {
day: "12",
month: "10",
year: null,
@ -23,28 +24,28 @@ o.spec("BirthdayUtilsTest", function () {
})
o("isoDateToBirthday", function () {
o(isoDateToBirthday("--10-12")).deepEquals(
createBirthday({
createTestEntity(BirthdayTypeRef, {
day: "12",
month: "10",
year: null,
}),
)
o(isoDateToBirthday("2009-10-12")).deepEquals(
createBirthday({
createTestEntity(BirthdayTypeRef, {
day: "12",
month: "10",
year: "2009",
}),
)
o(isoDateToBirthday("2009-12-31")).deepEquals(
createBirthday({
createTestEntity(BirthdayTypeRef, {
day: "31",
month: "12",
year: "2009",
}),
)
o(isoDateToBirthday("2009-01-01")).deepEquals(
createBirthday({
createTestEntity(BirthdayTypeRef, {
day: "01",
month: "01",
year: "2009",

View file

@ -11,9 +11,15 @@ import {
createWebsocketCounterValue,
createWebsocketEntityData,
EntityEventBatchTypeRef,
EntityUpdateTypeRef,
GroupMembershipTypeRef,
User,
UserTypeRef,
WebsocketCounterData,
WebsocketCounterDataTypeRef,
WebsocketCounterValueTypeRef,
WebsocketEntityData,
WebsocketEntityDataTypeRef,
} from "../../../../src/api/entities/sys/TypeRefs.js"
import { EntityRestClientMock } from "./rest/EntityRestClientMock.js"
import { EntityClient } from "../../../../src/api/common/EntityClient.js"
@ -28,6 +34,7 @@ import { SleepDetector } from "../../../../src/api/worker/utils/SleepDetector.js
import { WsConnectionState } from "../../../../src/api/main/WorkerClient.js"
import { UserFacade } from "../../../../src/api/worker/facades/UserFacade"
import { ExposedProgressTracker } from "../../../../src/api/main/ProgressTracker.js"
import { createTestEntity } from "../../TestUtils.js"
o.spec("EventBusClient test", function () {
let ebc: EventBusClient
@ -86,8 +93,8 @@ o.spec("EventBusClient test", function () {
},
} as DefaultEntityRestCache)
user = createUser({
userGroup: createGroupMembership({
user = createTestEntity(UserTypeRef, {
userGroup: createTestEntity(GroupMembershipTypeRef, {
group: "userGroupId",
}),
})
@ -111,7 +118,7 @@ o.spec("EventBusClient test", function () {
o.beforeEach(function () {
user.memberships = [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
groupType: GroupType.Mail,
group: mailGroupId,
}),
@ -121,7 +128,7 @@ o.spec("EventBusClient test", function () {
o("initial connect: when the cache is clean it downloads one batch and initializes cache", async function () {
when(cacheMock.getLastEntityEventBatchForGroup(mailGroupId)).thenResolve(null)
when(cacheMock.timeSinceLastSyncMs()).thenResolve(null)
const batch = createEntityEventBatch({ _id: [mailGroupId, "-----------1"] })
const batch = createTestEntity(EntityEventBatchTypeRef, { _id: [mailGroupId, "-----------1"] })
restClient.addListInstances(batch)
await ebc.connect(ConnectMode.Initial)
@ -136,13 +143,13 @@ o.spec("EventBusClient test", function () {
o("initial connect: when the cache is initialized, missed events are loaded", async function () {
when(cacheMock.getLastEntityEventBatchForGroup(mailGroupId)).thenResolve("------------")
when(cacheMock.timeSinceLastSyncMs()).thenResolve(1)
const update = createEntityUpdate({
const update = createTestEntity(EntityUpdateTypeRef, {
type: "Mail",
application: "tutanota",
instanceListId: mailGroupId,
instanceId: "newBatchId",
})
const batch = createEntityEventBatch({
const batch = createTestEntity(EntityEventBatchTypeRef, {
_id: [mailGroupId, "-----------1"],
events: [update],
})
@ -267,11 +274,11 @@ o.spec("EventBusClient test", function () {
})
function createEntityMessage(eventBatchId: number): string {
const event: WebsocketEntityData = createWebsocketEntityData({
const event: WebsocketEntityData = createTestEntity(WebsocketEntityDataTypeRef, {
eventBatchId: String(eventBatchId),
eventBatchOwner: "ownerId",
eventBatch: [
createEntityUpdate({
createTestEntity(EntityUpdateTypeRef, {
_id: "eventbatchid",
application: "tutanota",
type: "Mail",
@ -287,11 +294,11 @@ o.spec("EventBusClient test", function () {
type CounterMessageParams = { mailGroupId: Id; counterValue: number; listId: Id }
function createCounterData({ mailGroupId, counterValue, listId }: CounterMessageParams): WebsocketCounterData {
return createWebsocketCounterData({
return createTestEntity(WebsocketCounterDataTypeRef, {
_format: "0",
mailGroup: mailGroupId,
counterValues: [
createWebsocketCounterValue({
createTestEntity(WebsocketCounterValueTypeRef, {
_id: "counterupdateid",
count: String(counterValue),
mailListId: listId,

View file

@ -14,10 +14,9 @@ import { ProgrammingError } from "../../../../../src/api/common/error/Programmin
import { Cardinality, ValueType } from "../../../../../src/api/common/EntityConstants.js"
import { BucketPermissionType, PermissionType } from "../../../../../src/api/common/TutanotaConstants.js"
import {
BirthdayTypeRef,
ContactAddressTypeRef,
ContactTypeRef,
createBirthday,
createContact,
FileTypeRef,
Mail,
MailAddressTypeRef,
@ -29,20 +28,16 @@ import {
BucketKey,
BucketKeyTypeRef,
BucketPermissionTypeRef,
createBucket,
createBucketKey,
createBucketPermission,
createGroup,
createGroupMembership,
createInstanceSessionKey,
createKeyPair,
createPermission,
createTypeInfo,
createUser,
BucketTypeRef,
GroupMembershipTypeRef,
GroupTypeRef,
InstanceSessionKeyTypeRef,
KeyPairTypeRef,
PermissionTypeRef,
TypeInfoTypeRef,
UpdatePermissionKeyData,
UserIdReturnTypeRef,
UserTypeRef,
} from "../../../../../src/api/entities/sys/TypeRefs.js"
import { assertThrows, spy } from "@tutao/tutanota-test-utils"
import { RestClient } from "../../../../../src/api/worker/rest/RestClient.js"
@ -556,8 +551,8 @@ o.spec("crypto facade", function () {
const gk = aes128RandomKey()
const sk = aes128RandomKey()
when(userFacade.getGroupKey("mailGroupId")).thenReturn(gk)
const user = createUser({
userGroup: createGroupMembership({
const user = createTestEntity(UserTypeRef, {
userGroup: createTestEntity(GroupMembershipTypeRef, {
group: "mailGroupId",
}),
})
@ -584,22 +579,22 @@ o.spec("crypto facade", function () {
let bk = aes128RandomKey()
let privateKey = hexToPrivateKey(rsaPrivateHexKey)
let publicKey = hexToPublicKey(rsaPublicHexKey)
const keyPair = createKeyPair({
const keyPair = createTestEntity(KeyPairTypeRef, {
_id: "keyPairId",
symEncPrivKey: encryptRsaKey(gk, privateKey),
pubKey: hexToUint8Array(rsaPublicHexKey),
})
const userGroup = createGroup({
const userGroup = createTestEntity(GroupTypeRef, {
_id: "userGroupId",
keys: [keyPair],
})
const mail = createMailLiteral(gk, sk, subject, confidential, senderName, recipientName)
// @ts-ignore
mail._ownerEncSessionKey = null
const bucket = createBucket({
const bucket = createTestEntity(BucketTypeRef, {
bucketPermissions: "bucketPermissionListId",
})
const permission = createPermission({
const permission = createTestEntity(PermissionTypeRef, {
_id: ["permissionListId", "permissionId"],
_ownerGroup: userGroup._id,
bucketEncSessionKey: encryptKey(bk, sk),
@ -607,18 +602,18 @@ o.spec("crypto facade", function () {
type: PermissionType.Public,
})
const pubEncBucketKey = await rsaEncrypt(publicKey, bitArrayToUint8Array(bk))
const bucketPermission = createBucketPermission({
const bucketPermission = createTestEntity(BucketPermissionTypeRef, {
_id: ["bucketPermissionListId", "bucketPermissionId"],
_ownerGroup: userGroup._id,
type: BucketPermissionType.Public,
group: userGroup._id,
pubEncBucketKey,
})
const mem = createGroupMembership({
const mem = createTestEntity(GroupMembershipTypeRef, {
group: userGroup._id,
})
const user = createUser({
const user = createTestEntity(UserTypeRef, {
userGroup: mem,
})
when(userFacade.getLoggedInUser()).thenReturn(user)
@ -671,7 +666,7 @@ o.spec("crypto facade", function () {
})
o("contact migration without existing birthday", async function () {
const contact = createContact({
const contact = createTestEntity(ContactTypeRef, {
birthdayIso: "2019-05-01",
})
@ -682,7 +677,7 @@ o.spec("crypto facade", function () {
})
o("contact migration without existing birthday and oldBirthdayDate", async function () {
const contact = createContact({
const contact = createTestEntity(ContactTypeRef, {
_id: ["listid", "id"],
birthdayIso: "2019-05-01",
oldBirthdayDate: new Date(2000, 4, 1),
@ -696,10 +691,10 @@ o.spec("crypto facade", function () {
})
o("contact migration with existing birthday and oldBirthdayAggregate", async function () {
const contact = createContact({
const contact = createTestEntity(ContactTypeRef, {
_id: ["listid", "id"],
birthdayIso: "2019-05-01",
oldBirthdayAggregate: createBirthday({
oldBirthdayAggregate: createTestEntity(BirthdayTypeRef, {
day: "01",
month: "05",
year: "2000",
@ -715,10 +710,10 @@ o.spec("crypto facade", function () {
})
o("contact migration from oldBirthdayAggregate", async function () {
const contact = createContact({
const contact = createTestEntity(ContactTypeRef, {
_id: ["listid", "id"],
oldBirthdayDate: new Date(1800, 4, 1),
oldBirthdayAggregate: createBirthday({
oldBirthdayAggregate: createTestEntity(BirthdayTypeRef, {
day: "01",
month: "05",
year: "2000",
@ -734,7 +729,7 @@ o.spec("crypto facade", function () {
})
o("contact migration from oldBirthdayDate", async function () {
const contact = createContact({
const contact = createTestEntity(ContactTypeRef, {
_id: ["listid", "id"],
birthdayIso: null,
oldBirthdayDate: new Date(1800, 4, 1),
@ -750,11 +745,11 @@ o.spec("crypto facade", function () {
})
o("contact migration from oldBirthdayAggregate without year", async function () {
const contact = createContact({
const contact = createTestEntity(ContactTypeRef, {
_id: ["listid", "id"],
birthdayIso: null,
oldBirthdayDate: null,
oldBirthdayAggregate: createBirthday({
oldBirthdayAggregate: createTestEntity(BirthdayTypeRef, {
day: "01",
month: "05",
year: null,
@ -947,12 +942,12 @@ o.spec("crypto facade", function () {
let bk = aes128RandomKey()
let privateKey = hexToPrivateKey(rsaPrivateHexKey)
let publicKey = hexToPublicKey(rsaPublicHexKey)
const keyPair = createKeyPair({
const keyPair = createTestEntity(KeyPairTypeRef, {
_id: "keyPairId",
symEncPrivKey: encryptRsaKey(userGk, privateKey),
pubKey: hexToUint8Array(rsaPublicHexKey),
})
const userGroup = createGroup({
const userGroup = createTestEntity(GroupTypeRef, {
_id: "userGroupId",
keys: [keyPair],
})
@ -966,8 +961,8 @@ o.spec("crypto facade", function () {
const MailTypeModel = await resolveTypeReference(MailTypeRef)
typeModels.tutanota
const mailInstanceSessionKey = createInstanceSessionKey({
typeInfo: createTypeInfo({
const mailInstanceSessionKey = createTestEntity(InstanceSessionKeyTypeRef, {
typeInfo: createTestEntity(TypeInfoTypeRef, {
application: MailTypeModel.app,
typeId: String(MailTypeModel.id),
}),
@ -977,8 +972,8 @@ o.spec("crypto facade", function () {
})
const FileTypeModel = await resolveTypeReference(FileTypeRef)
const bucketEncSessionKeys = fileSessionKeys.map((fileSessionKey, index) => {
return createInstanceSessionKey({
typeInfo: createTypeInfo({
return createTestEntity(InstanceSessionKeyTypeRef, {
typeInfo: createTestEntity(TypeInfoTypeRef, {
application: FileTypeModel.app,
typeId: String(FileTypeModel.id),
}),
@ -989,7 +984,7 @@ o.spec("crypto facade", function () {
})
bucketEncSessionKeys.push(mailInstanceSessionKey)
const bucketKey = createBucketKey({
const bucketKey = createTestEntity(BucketKeyTypeRef, {
pubEncBucketKey: pubEncBucketKey,
keyGroup: userGroup._id,
bucketEncSessionKeys: bucketEncSessionKeys,
@ -999,11 +994,11 @@ o.spec("crypto facade", function () {
const bucketKeyLiteral = await instanceMapper.encryptAndMapToLiteral(BucketKeyModel, bucketKey, null)
Object.assign(mailLiteral, { bucketKey: bucketKeyLiteral })
const mem = createGroupMembership({
const mem = createTestEntity(GroupMembershipTypeRef, {
group: userGroup._id,
})
const user = createUser({
const user = createTestEntity(UserTypeRef, {
userGroup: mem,
})
@ -1050,7 +1045,7 @@ o.spec("crypto facade", function () {
let bk = aes128RandomKey()
const ugk = aes128RandomKey()
const userGroup = createGroup({
const userGroup = createTestEntity(GroupTypeRef, {
_id: "userGroupId",
keys: [],
})
@ -1066,8 +1061,8 @@ o.spec("crypto facade", function () {
const MailTypeModel = await resolveTypeReference(MailTypeRef)
typeModels.tutanota
const mailInstanceSessionKey = createInstanceSessionKey({
typeInfo: createTypeInfo({
const mailInstanceSessionKey = createTestEntity(InstanceSessionKeyTypeRef, {
typeInfo: createTestEntity(TypeInfoTypeRef, {
application: MailTypeModel.app,
typeId: String(MailTypeModel.id),
}),
@ -1077,8 +1072,8 @@ o.spec("crypto facade", function () {
})
const FileTypeModel = await resolveTypeReference(FileTypeRef)
const bucketEncSessionKeys = fileSessionKeys.map((fileSessionKey, index) => {
return createInstanceSessionKey({
typeInfo: createTypeInfo({
return createTestEntity(InstanceSessionKeyTypeRef, {
typeInfo: createTestEntity(TypeInfoTypeRef, {
application: FileTypeModel.app,
typeId: String(FileTypeModel.id),
}),
@ -1089,7 +1084,7 @@ o.spec("crypto facade", function () {
})
bucketEncSessionKeys.push(mailInstanceSessionKey)
const bucketKey = createBucketKey({
const bucketKey = createTestEntity(BucketKeyTypeRef, {
pubEncBucketKey: null,
keyGroup: externalUserGroupEncBucketKey ? userGroup._id : null,
groupEncBucketKey: groupEncBucketKey,
@ -1100,11 +1095,11 @@ o.spec("crypto facade", function () {
const bucketKeyLiteral = await instanceMapper.encryptAndMapToLiteral(BucketKeyModel, bucketKey, null)
Object.assign(mailLiteral, { bucketKey: bucketKeyLiteral })
const mem = createGroupMembership({
const mem = createTestEntity(GroupMembershipTypeRef, {
group: userGroup._id,
})
const user = createUser({
const user = createTestEntity(UserTypeRef, {
userGroup: mem,
})

View file

@ -26,13 +26,13 @@ o.spec("OwnerEncSessionKeysUpdateQueue", function () {
o.spec("updateInstanceSessionKeys", function () {
o("send updates from queue", async function () {
const updatableInstanceSessionKeys = [
createInstanceSessionKey({
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "mailInstanceId",
instanceList: "mailInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
symEncSessionKey: new Uint8Array([1, 2, 3]),
}),
createInstanceSessionKey({
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "fileInstanceId",
instanceList: "fileInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
@ -64,13 +64,13 @@ o.spec("OwnerEncSessionKeysUpdateQueue", function () {
}
})
const updatableInstanceSessionKeys = [
createInstanceSessionKey({
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "mailInstanceId",
instanceList: "mailInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
symEncSessionKey: new Uint8Array([1, 2, 3]),
}),
createInstanceSessionKey({
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "fileInstanceId",
instanceList: "fileInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
@ -93,13 +93,13 @@ o.spec("OwnerEncSessionKeysUpdateQueue", function () {
o("debounced request sends entire queue", async function () {
const updatableInstanceSessionKeys = [
createInstanceSessionKey({
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "mailInstanceId",
instanceList: "mailInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
symEncSessionKey: new Uint8Array([1, 2, 3]),
}),
createInstanceSessionKey({
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "fileInstanceId",
instanceList: "fileInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),

View file

@ -1,23 +1,24 @@
import o from "@tutao/otest"
import { ArchiveDataType } from "../../../../../src/api/common/TutanotaConstants.js"
import { createBlob } from "../../../../../src/api/entities/sys/TypeRefs.js"
import { createFile, createMailBody } from "../../../../../src/api/entities/tutanota/TypeRefs.js"
import { ServiceExecutor } from "../../../../../src/api/worker/rest/ServiceExecutor.js"
import { matchers, object, verify, when } from "testdouble"
import { BlobAccessTokenService } from "../../../../../src/api/entities/storage/Services.js"
import { getElementId, getEtId, getListId } from "../../../../../src/api/common/utils/EntityUtils.js"
import { Mode } from "../../../../../src/api/common/Env.js"
import {
createBlobAccessTokenPostIn,
createBlobAccessTokenPostOut,
createBlobReadData,
createBlobServerAccessInfo,
createBlobWriteData,
createInstanceId,
} from "../../../../../src/api/entities/storage/TypeRefs.js"
import { BlobAccessTokenFacade, BlobReferencingInstance } from "../../../../../src/api/worker/facades/BlobAccessTokenFacade.js"
import { DateTime } from "luxon"
import { AuthDataProvider } from "../../../../../src/api/worker/facades/UserFacade.js"
import {
BlobAccessTokenPostInTypeRef,
BlobAccessTokenPostOutTypeRef,
BlobReadDataTypeRef,
BlobServerAccessInfoTypeRef,
BlobWriteDataTypeRef,
InstanceIdTypeRef,
} from "../../../../../src/api/entities/storage/TypeRefs.js"
import { createTestEntity } from "../../../TestUtils.js"
import { FileTypeRef, MailBodyTypeRef } from "../../../../../src/api/entities/tutanota/TypeRefs.js"
import { BlobTypeRef } from "../../../../../src/api/entities/sys/TypeRefs.js"
const { anything, captor } = matchers
@ -28,7 +29,12 @@ o.spec("BlobAccessTokenFacade test", function () {
let authDataProvider: AuthDataProvider
const archiveId = "archiveId1"
const blobId1 = "blobId1"
const blobs = [createBlob({ archiveId, blobId: blobId1 }), createBlob({ archiveId, blobId: "blobId2" }), createBlob({ archiveId })]
// @ts-ignore
const blobs = [
createTestEntity(BlobTypeRef, { archiveId, blobId: blobId1 }),
createTestEntity(BlobTypeRef, { archiveId, blobId: "blobId2" }),
createTestEntity(BlobTypeRef, { archiveId }),
]
let now: DateTime
o.beforeEach(function () {
@ -48,8 +54,10 @@ o.spec("BlobAccessTokenFacade test", function () {
o.spec("evict Tokens", function () {
o("evict blob specific read token", async function () {
const file = createFile({ blobs, _id: ["listId", "elementId"] })
const expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "123" }) })
const file = createTestEntity(FileTypeRef, { blobs, _id: ["listId", "elementId"] })
const expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123" }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
const referencingInstance: BlobReferencingInstance = {
blobs,
@ -60,35 +68,41 @@ o.spec("BlobAccessTokenFacade test", function () {
await blobAccessTokenFacade.requestReadTokenBlobs(archiveDataType, referencingInstance)
blobAccessTokenFacade.evictReadBlobsToken(referencingInstance)
const newToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "456" }) })
const newToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "456" }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(newToken)
const readToken = await blobAccessTokenFacade.requestReadTokenBlobs(archiveDataType, referencingInstance)
o(readToken).equals(newToken.blobAccessInfo)
})
o("evict archive read token", async function () {
let blobAccessInfo = createBlobServerAccessInfo({ blobAccessToken: "123" })
const expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo })
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123" })
const expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, { blobAccessInfo })
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
await blobAccessTokenFacade.requestReadTokenArchive(archiveId)
blobAccessTokenFacade.evictArchiveToken(archiveId)
const newToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "456" }) })
const newToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "456" }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(newToken)
const readToken = await blobAccessTokenFacade.requestReadTokenArchive(archiveId)
o(readToken).equals(newToken.blobAccessInfo)
})
o("evict archive write token", async function () {
let blobAccessInfo = createBlobServerAccessInfo({ blobAccessToken: "123" })
const expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo })
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123" })
const expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, { blobAccessInfo })
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
const ownerGroupId = "ownerGroupId"
const archiveDataType = ArchiveDataType.Attachments
await blobAccessTokenFacade.requestWriteToken(archiveDataType, ownerGroupId)
blobAccessTokenFacade.evictWriteToken(archiveDataType, ownerGroupId)
const newToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "456" }) })
const newToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "456" }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(newToken)
const readToken = await blobAccessTokenFacade.requestWriteToken(archiveDataType, ownerGroupId)
o(readToken).equals(newToken.blobAccessInfo)
@ -98,8 +112,10 @@ o.spec("BlobAccessTokenFacade test", function () {
o.spec("request access tokens", function () {
o.spec("read token for specific blobs", function () {
o("read token LET", async function () {
const file = createFile({ blobs, _id: ["listId", "elementId"] })
const expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "123" }) })
const file = createTestEntity(FileTypeRef, { blobs, _id: ["listId", "elementId"] })
const expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123" }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
const referencingInstance: BlobReferencingInstance = {
@ -112,11 +128,11 @@ o.spec("BlobAccessTokenFacade test", function () {
const tokenRequest = captor()
verify(serviceMock.post(BlobAccessTokenService, tokenRequest.capture()))
let instanceId = createInstanceId({ instanceId: getElementId(file) })
let instanceId = createTestEntity(InstanceIdTypeRef, { instanceId: getElementId(file) })
o(tokenRequest.value).deepEquals(
createBlobAccessTokenPostIn({
createTestEntity(BlobAccessTokenPostInTypeRef, {
archiveDataType,
read: createBlobReadData({
read: createTestEntity(BlobReadDataTypeRef, {
archiveId,
instanceListId: getListId(file),
instanceIds: [instanceId],
@ -127,8 +143,10 @@ o.spec("BlobAccessTokenFacade test", function () {
})
o("read token ET", async function () {
const mailBody = createMailBody({ _id: "elementId" })
const expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "123" }) })
const mailBody = createTestEntity(MailBodyTypeRef, { _id: "elementId" })
const expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123" }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
const referencingInstance: BlobReferencingInstance = {
@ -141,11 +159,11 @@ o.spec("BlobAccessTokenFacade test", function () {
const tokenRequest = captor()
verify(serviceMock.post(BlobAccessTokenService, tokenRequest.capture()))
let instanceId = createInstanceId({ instanceId: getEtId(mailBody) })
let instanceId = createTestEntity(InstanceIdTypeRef, { instanceId: getEtId(mailBody) })
o(tokenRequest.value).deepEquals(
createBlobAccessTokenPostIn({
createTestEntity(BlobAccessTokenPostInTypeRef, {
archiveDataType,
read: createBlobReadData({
read: createTestEntity(BlobReadDataTypeRef, {
archiveId,
instanceListId: null,
instanceIds: [instanceId],
@ -157,8 +175,8 @@ o.spec("BlobAccessTokenFacade test", function () {
})
o("request read token archive", async function () {
let blobAccessInfo = createBlobServerAccessInfo({ blobAccessToken: "123" })
const expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo })
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123" })
const expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, { blobAccessInfo })
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
const readToken = await blobAccessTokenFacade.requestReadTokenArchive(archiveId)
@ -166,8 +184,8 @@ o.spec("BlobAccessTokenFacade test", function () {
const tokenRequest = captor()
verify(serviceMock.post(BlobAccessTokenService, tokenRequest.capture()))
o(tokenRequest.value).deepEquals(
createBlobAccessTokenPostIn({
read: createBlobReadData({
createTestEntity(BlobAccessTokenPostInTypeRef, {
read: createTestEntity(BlobReadDataTypeRef, {
archiveId,
instanceListId: null,
instanceIds: [],
@ -178,8 +196,8 @@ o.spec("BlobAccessTokenFacade test", function () {
})
o("cache read token for an entire archive", async function () {
let blobAccessInfo = createBlobServerAccessInfo({ blobAccessToken: "123" })
const expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo })
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123" })
const expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, { blobAccessInfo })
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
await blobAccessTokenFacade.requestReadTokenArchive(archiveId)
@ -194,14 +212,14 @@ o.spec("BlobAccessTokenFacade test", function () {
o("cache read token archive expired", async function () {
let expires = new Date(now.toMillis() - 1) // date in the past, so the token is expired
let blobAccessInfo = createBlobServerAccessInfo({ blobAccessToken: "123", expires })
let expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo })
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123", expires })
let expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, { blobAccessInfo })
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
await blobAccessTokenFacade.requestReadTokenArchive(archiveId)
blobAccessInfo = createBlobServerAccessInfo({ blobAccessToken: "456" })
expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo })
blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "456" })
expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, { blobAccessInfo })
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
// request it twice and verify that there is only one network request
@ -215,7 +233,9 @@ o.spec("BlobAccessTokenFacade test", function () {
o("request write token", async function () {
const ownerGroup = "ownerId"
const expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "123" }) })
const expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123" }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
const writeToken = await blobAccessTokenFacade.requestWriteToken(archiveDataType, ownerGroup)
@ -223,9 +243,9 @@ o.spec("BlobAccessTokenFacade test", function () {
const tokenRequest = captor()
verify(serviceMock.post(BlobAccessTokenService, tokenRequest.capture()))
o(tokenRequest.value).deepEquals(
createBlobAccessTokenPostIn({
createTestEntity(BlobAccessTokenPostInTypeRef, {
archiveDataType,
write: createBlobWriteData({
write: createTestEntity(BlobWriteDataTypeRef, {
archiveOwnerGroup: ownerGroup,
}),
}),
@ -235,7 +255,9 @@ o.spec("BlobAccessTokenFacade test", function () {
o("cache write token", async function () {
const ownerGroup = "ownerId"
const expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "123" }) })
const expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123" }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
await blobAccessTokenFacade.requestWriteToken(archiveDataType, ownerGroup)
@ -250,12 +272,16 @@ o.spec("BlobAccessTokenFacade test", function () {
o("cache write token expired", async function () {
let expires = new Date(now.toMillis() - 1) // date in the past, so the token is expired
const ownerGroup = "ownerId"
let expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "123", expires }) })
let expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "123", expires }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
await blobAccessTokenFacade.requestWriteToken(archiveDataType, ownerGroup)
expectedToken = createBlobAccessTokenPostOut({ blobAccessInfo: createBlobServerAccessInfo({ blobAccessToken: "456" }) })
expectedToken = createTestEntity(BlobAccessTokenPostOutTypeRef, {
blobAccessInfo: createTestEntity(BlobServerAccessInfoTypeRef, { blobAccessToken: "456" }),
})
when(serviceMock.post(BlobAccessTokenService, anything())).thenResolve(expectedToken)
const writeToken = await blobAccessTokenFacade.requestWriteToken(archiveDataType, ownerGroup)

View file

@ -6,8 +6,8 @@ import { NativeFileApp } from "../../../../../src/native/common/FileApp.js"
import { AesApp } from "../../../../../src/native/worker/AesApp.js"
import { InstanceMapper } from "../../../../../src/api/worker/crypto/InstanceMapper.js"
import { ArchiveDataType, MAX_BLOB_SIZE_BYTES } from "../../../../../src/api/common/TutanotaConstants.js"
import { BlobTypeRef, createBlob, createBlobReferenceTokenWrapper } from "../../../../../src/api/entities/sys/TypeRefs.js"
import { createFile, File as TutanotaFile } from "../../../../../src/api/entities/tutanota/TypeRefs.js"
import { BlobReferenceTokenWrapperTypeRef, BlobTypeRef, createBlob, createBlobReferenceTokenWrapper } from "../../../../../src/api/entities/sys/TypeRefs.js"
import { createFile, File as TutanotaFile, FileTypeRef } from "../../../../../src/api/entities/tutanota/TypeRefs.js"
import { ServiceExecutor } from "../../../../../src/api/worker/rest/ServiceExecutor.js"
import { instance, matchers, object, verify, when } from "testdouble"
import { HttpMethod } from "../../../../../src/api/common/EntityFunctions.js"
@ -18,7 +18,14 @@ import { CryptoFacade } from "../../../../../src/api/worker/crypto/CryptoFacade.
import { FileReference } from "../../../../../src/api/common/utils/FileUtils.js"
import { assertThrows } from "@tutao/tutanota-test-utils"
import { ProgrammingError } from "../../../../../src/api/common/error/ProgrammingError.js"
import { createBlobPostOut, createBlobServerAccessInfo, createBlobServerUrl } from "../../../../../src/api/entities/storage/TypeRefs.js"
import {
BlobPostOutTypeRef,
BlobServerAccessInfoTypeRef,
BlobServerUrlTypeRef,
createBlobPostOut,
createBlobServerAccessInfo,
createBlobServerUrl,
} from "../../../../../src/api/entities/storage/TypeRefs.js"
import type { AuthDataProvider } from "../../../../../src/api/worker/facades/UserFacade.js"
import { BlobAccessTokenFacade, BlobReferencingInstance } from "../../../../../src/api/worker/facades/BlobAccessTokenFacade.js"
import { DateProvider } from "../../../../../src/api/common/DateProvider.js"
@ -39,7 +46,11 @@ o.spec("BlobFacade test", function () {
let instanceMapperMock: InstanceMapper
const archiveId = "archiveId1"
const blobId1 = "blobId1"
const blobs = [createBlob({ archiveId, blobId: blobId1 }), createBlob({ archiveId, blobId: "blobId2" }), createBlob({ archiveId })]
const blobs = [
createTestEntity(BlobTypeRef, { archiveId, blobId: blobId1 }),
createTestEntity(BlobTypeRef, { archiveId, blobId: "blobId2" }),
createTestEntity(BlobTypeRef, { archiveId }),
]
let archiveDataType = ArchiveDataType.Attachments
let cryptoFacadeMock: CryptoFacade
let dateProvider: DateProvider
@ -58,7 +69,7 @@ o.spec("BlobFacade test", function () {
const mimeType = "text/plain"
const name = "fileName"
file = createFile({ name, mimeType, _id: ["fileListId", "fileElementId"] })
file = createTestEntity(FileTypeRef, { name, mimeType, _id: ["fileListId", "fileElementId"] })
blobFacade = new BlobFacade(
authDataProvider,
@ -83,11 +94,14 @@ o.spec("BlobFacade test", function () {
const sessionKey = aes128RandomKey()
const blobData = new Uint8Array([1, 2, 3])
const expectedReferenceTokens = [createBlobReferenceTokenWrapper({ blobReferenceToken: "blobRefToken" })]
const expectedReferenceTokens = [createTestEntity(BlobReferenceTokenWrapperTypeRef, { blobReferenceToken: "blobRefToken" })]
let blobAccessInfo = createBlobServerAccessInfo({ blobAccessToken: "123", servers: [createBlobServerUrl({ url: "w1" })] })
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, {
blobAccessToken: "123",
servers: [createTestEntity(BlobServerUrlTypeRef, { url: "w1" })],
})
when(blobAccessTokenFacade.requestWriteToken(anything(), anything())).thenResolve(blobAccessInfo)
let blobServiceResponse = createBlobPostOut({ blobReferenceToken: expectedReferenceTokens[0].blobReferenceToken })
let blobServiceResponse = createTestEntity(BlobPostOutTypeRef, { blobReferenceToken: expectedReferenceTokens[0].blobReferenceToken })
when(instanceMapperMock.decryptAndMapToInstance(anything(), anything(), anything())).thenResolve(blobServiceResponse)
when(restClientMock.request(BLOB_SERVICE_REST_PATH, HttpMethod.POST, anything())).thenResolve(JSON.stringify(blobServiceResponse))
@ -106,16 +120,16 @@ o.spec("BlobFacade test", function () {
const ownerGroup = "ownerId"
const sessionKey = aes128RandomKey()
const expectedReferenceTokens = [createBlobReferenceTokenWrapper({ blobReferenceToken: "blobRefToken" })]
const expectedReferenceTokens = [createTestEntity(BlobReferenceTokenWrapperTypeRef, { blobReferenceToken: "blobRefToken" })]
const uploadedFileUri = "rawFileUri"
const chunkUris = ["uri1"]
let blobAccessInfo = createBlobServerAccessInfo({
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, {
blobAccessToken: "123",
servers: [createBlobServerUrl({ url: "http://w1.api.tuta.com" })],
servers: [createTestEntity(BlobServerUrlTypeRef, { url: "http://w1.api.tuta.com" })],
})
when(blobAccessTokenFacade.requestWriteToken(anything(), anything())).thenResolve(blobAccessInfo)
let blobServiceResponse = createBlobPostOut({ blobReferenceToken: expectedReferenceTokens[0].blobReferenceToken })
let blobServiceResponse = createTestEntity(BlobPostOutTypeRef, { blobReferenceToken: expectedReferenceTokens[0].blobReferenceToken })
when(blobAccessTokenFacade.createQueryParams(blobAccessInfo, anything(), anything())).thenResolve({ test: "theseAreTheParamsIPromise" })
when(instanceMapperMock.decryptAndMapToInstance(anything(), anything(), anything())).thenResolve(blobServiceResponse)
@ -154,7 +168,10 @@ o.spec("BlobFacade test", function () {
file.blobs.push(createTestEntity(BlobTypeRef))
const encryptedBlobData = aesEncrypt(sessionKey, blobData, generateIV(), true, true)
let blobAccessInfo = createBlobServerAccessInfo({ blobAccessToken: "123", servers: [createBlobServerUrl({ url: "someBaseUrl" })] })
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, {
blobAccessToken: "123",
servers: [createTestEntity(BlobServerUrlTypeRef, { url: "someBaseUrl" })],
})
when(blobAccessTokenFacade.requestReadTokenBlobs(anything(), anything())).thenResolve(blobAccessInfo)
when(blobAccessTokenFacade.createQueryParams(blobAccessInfo, anything(), anything())).thenResolve({
baseUrl: "someBaseUrl",
@ -180,9 +197,9 @@ o.spec("BlobFacade test", function () {
file.blobs.push(blobs[0])
let blobAccessInfo = createBlobServerAccessInfo({
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, {
blobAccessToken: "123",
servers: [createBlobServerUrl({ url: "http://w1.api.tuta.com" })],
servers: [createTestEntity(BlobServerUrlTypeRef, { url: "http://w1.api.tuta.com" })],
})
when(blobAccessTokenFacade.requestReadTokenBlobs(anything(), anything())).thenResolve(blobAccessInfo)
when(blobAccessTokenFacade.createQueryParams(anything(), anything(), anything())).thenResolve({ test: "theseAreTheParamsIPromise" })
@ -226,9 +243,9 @@ o.spec("BlobFacade test", function () {
file.blobs.push(blobs[0])
file.blobs.push(blobs[1])
let blobAccessInfo = createBlobServerAccessInfo({
let blobAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, {
blobAccessToken: "123",
servers: [createBlobServerUrl({ url: "http://w1.api.tuta.com" })],
servers: [createTestEntity(BlobServerUrlTypeRef, { url: "http://w1.api.tuta.com" })],
})
when(blobAccessTokenFacade.requestReadTokenBlobs(anything(), anything())).thenResolve(blobAccessInfo)
when(cryptoFacadeMock.resolveSessionKeyForInstance(file)).thenResolve(sessionKey)

View file

@ -6,14 +6,19 @@ import { DefaultEntityRestCache } from "../../../../../src/api/worker/rest/Defau
import { clone, downcast, isSameTypeRef, neverNull, noOp } from "@tutao/tutanota-utils"
import type { AlarmInfo, User, UserAlarmInfo } from "../../../../../src/api/entities/sys/TypeRefs.js"
import {
AlarmInfoTypeRef,
CalendarEventRefTypeRef,
createAlarmInfo,
createCalendarEventRef,
createPushIdentifierList,
createUser,
createUserAlarmInfo,
createUserAlarmInfoListType,
PushIdentifierListTypeRef,
PushIdentifierTypeRef,
UserAlarmInfoListTypeTypeRef,
UserAlarmInfoTypeRef,
UserTypeRef,
} from "../../../../../src/api/entities/sys/TypeRefs.js"
import { getElementId, getLetId, getListId } from "../../../../../src/api/common/utils/EntityUtils.js"
import type { CalendarEvent } from "../../../../../src/api/entities/tutanota/TypeRefs.js"
@ -31,6 +36,7 @@ import { UserFacade } from "../../../../../src/api/worker/facades/UserFacade"
import { InfoMessageHandler } from "../../../../../src/gui/InfoMessageHandler.js"
import { ConnectionError } from "../../../../../src/api/common/error/RestError.js"
import { EntityClient } from "../../../../../src/api/common/EntityClient.js"
import { createTestEntity } from "../../../TestUtils.js"
o.spec("CalendarFacadeTest", async function () {
let userAlarmInfoListId: Id
@ -71,22 +77,22 @@ o.spec("CalendarFacadeTest", async function () {
}
function makeEvent(listId: Id, elementId?: Id): CalendarEvent {
return createCalendarEvent({
return createTestEntity(CalendarEventTypeRef, {
_id: [listId, elementId || restClientMock.getNextId()],
uid: `${listId}-${elementId}`,
})
}
function makeUserAlarmInfo(event: CalendarEvent): UserAlarmInfo {
return createUserAlarmInfo({
return createTestEntity(UserAlarmInfoTypeRef, {
_id: [userAlarmInfoListId, restClientMock.getNextId()],
alarmInfo: makeAlarmInfo(event),
})
}
function makeAlarmInfo(event: CalendarEvent): AlarmInfo {
return createAlarmInfo({
calendarRef: createCalendarEventRef({
return createTestEntity(AlarmInfoTypeRef, {
calendarRef: createTestEntity(CalendarEventRefTypeRef, {
elementId: getElementId(event),
listId: getListId(event),
}),
@ -97,11 +103,11 @@ o.spec("CalendarFacadeTest", async function () {
restClientMock = new EntityRestClientMock()
userAlarmInfoListId = restClientMock.getNextId()
user = createUser({
alarmInfoList: createUserAlarmInfoListType({
user = createTestEntity(UserTypeRef, {
alarmInfoList: createTestEntity(UserAlarmInfoListTypeTypeRef, {
alarms: userAlarmInfoListId,
}),
pushIdentifierList: createPushIdentifierList({ list: "pushIdentifierList" }),
pushIdentifierList: createTestEntity(PushIdentifierListTypeRef, { list: "pushIdentifierList" }),
userGroup: downcast({
group: "Id",
}),
@ -435,7 +441,7 @@ o.spec("CalendarFacadeTest", async function () {
})
o("sorts array with len 1", function () {
const arr = [createCalendarEvent({ recurrenceId: new Date("2023-07-17T13:00") })] as Array<CalendarEventAlteredInstance>
const arr = [createTestEntity(CalendarEventTypeRef, { recurrenceId: new Date("2023-07-17T13:00") })] as Array<CalendarEventAlteredInstance>
const expected = clone(arr)
sortByRecurrenceId(arr)
o(arr).deepEquals(expected)
@ -443,8 +449,8 @@ o.spec("CalendarFacadeTest", async function () {
o("sorts array that's not sorted", function () {
const arr = [
createCalendarEvent({ recurrenceId: new Date("2023-07-17T13:00") }),
createCalendarEvent({ recurrenceId: new Date("2023-07-16T13:00") }),
createTestEntity(CalendarEventTypeRef, { recurrenceId: new Date("2023-07-17T13:00") }),
createTestEntity(CalendarEventTypeRef, { recurrenceId: new Date("2023-07-16T13:00") }),
] as Array<CalendarEventAlteredInstance>
const expected = clone(arr)
const smaller = expected[1]

View file

@ -5,10 +5,14 @@ import {
createGroupInfo,
createGroupMembership,
createSaltReturn,
CreateSessionReturnTypeRef,
createUser,
createUserExternalAuthInfo,
GroupInfoTypeRef,
GroupMembershipTypeRef,
SaltReturnTypeRef,
User,
UserExternalAuthInfoTypeRef,
UserTypeRef,
} from "../../../../../src/api/entities/sys/TypeRefs"
import { createAuthVerifier, encryptKey, keyToBase64, sha256Hash } from "@tutao/tutanota-crypto"
@ -65,15 +69,15 @@ async function makeUser({ id, passphrase, salt }, facade: LoginFacade): Promise<
const groupKey = encryptKey(userPassphraseKey, [3229306880, 2716953871, 4072167920, 3901332676])
return createUser({
return createTestEntity(UserTypeRef, {
_id: id,
verifier: sha256Hash(createAuthVerifier(userPassphraseKey)),
userGroup: createGroupMembership({
userGroup: createTestEntity(GroupMembershipTypeRef, {
group: "groupId",
symEncGKey: groupKey,
groupInfo: ["groupInfoListId", "groupInfoElId"],
}),
externalAuthInfo: createUserExternalAuthInfo({
externalAuthInfo: createTestEntity(UserExternalAuthInfoTypeRef, {
latestSaltHash: SALT,
}),
})
@ -102,7 +106,7 @@ o.spec("LoginFacadeTest", function () {
o.beforeEach(function () {
workerMock = instance(WorkerImpl)
serviceExecutor = object()
when(serviceExecutor.get(SaltService, anything()), { ignoreExtraArgs: true }).thenResolve(createSaltReturn({ salt: SALT }))
when(serviceExecutor.get(SaltService, anything()), { ignoreExtraArgs: true }).thenResolve(createTestEntity(SaltReturnTypeRef, { salt: SALT }))
restClientMock = instance(RestClient)
entityClientMock = instance(EntityClient)
@ -165,7 +169,7 @@ o.spec("LoginFacadeTest", function () {
o.beforeEach(async function () {
when(serviceExecutor.post(SessionService, anything()), { ignoreExtraArgs: true }).thenResolve(
createCreateSessionReturn({ user: userId, accessToken: "accessToken", challenges: [] }),
createTestEntity(CreateSessionReturnTypeRef, { user: userId, accessToken: "accessToken", challenges: [] }),
)
when(entityClientMock.load(UserTypeRef, userId)).thenResolve(
await makeUser(
@ -618,7 +622,7 @@ o.spec("LoginFacadeTest", function () {
},
facade,
)
user.externalAuthInfo = createUserExternalAuthInfo({
user.externalAuthInfo = createTestEntity(UserExternalAuthInfoTypeRef, {
latestSaltHash: sha256Hash(SALT),
})

View file

@ -11,6 +11,7 @@ import {
createMailAddressProperties,
createMailboxGroupRoot,
createMailboxProperties,
MailAddressPropertiesTypeRef,
MailboxGroupRootTypeRef,
MailboxPropertiesTypeRef,
} from "../../../../../src/api/entities/tutanota/TypeRefs.js"
@ -21,9 +22,12 @@ import {
createMailAddressAlias,
createUser,
GroupInfoTypeRef,
GroupMembershipTypeRef,
MailAddressAliasTypeRef,
UserTypeRef,
} from "../../../../../src/api/entities/sys/TypeRefs.js"
import { MailAddressFacade } from "../../../../../src/api/worker/facades/lazy/MailAddressFacade.js"
import { createTestEntity } from "../../../TestUtils.js"
o.spec("MailAddressFacadeTest", function () {
let worker: WorkerImpl
@ -51,18 +55,18 @@ o.spec("MailAddressFacadeTest", function () {
const mailGroupId = "mailGroupId"
const viaUser = "viaUser"
const mailboxPropertiesId = "mailboxPropertiesId"
const mailboxGroupRoot = createMailboxGroupRoot({
const mailboxGroupRoot = createTestEntity(MailboxGroupRootTypeRef, {
_ownerGroup: mailGroupId,
mailboxProperties: mailboxPropertiesId,
})
const mailGroupKey = [1, 2, 3]
const mailboxProperties = createMailboxProperties({
const mailboxProperties = createTestEntity(MailboxPropertiesTypeRef, {
mailAddressProperties: [
createMailAddressProperties({
createTestEntity(MailAddressPropertiesTypeRef, {
mailAddress: "a@a.com",
senderName: "a",
}),
createMailAddressProperties({
createTestEntity(MailAddressPropertiesTypeRef, {
mailAddress: "b@b.com",
senderName: "b",
}),
@ -84,30 +88,30 @@ o.spec("MailAddressFacadeTest", function () {
const mailGroupId = "mailGroupId"
const viaUser = "viaUser"
const mailboxPropertiesId = "mailboxProeprtiesId"
const mailboxGroupRoot = createMailboxGroupRoot({
const mailboxGroupRoot = createTestEntity(MailboxGroupRootTypeRef, {
_ownerGroup: mailGroupId,
mailboxProperties: null,
})
const mailGroupKey = [1, 2, 3]
const mailboxProperties = createMailboxProperties({
const mailboxProperties = createTestEntity(MailboxPropertiesTypeRef, {
_id: mailboxPropertiesId,
_ownerGroup: mailGroupId,
reportMovedMails: "",
mailAddressProperties: [],
})
const userGroupInfoId: IdTuple = ["groupInfoListId", "groupInfoId"]
const user = createUser({
const user = createTestEntity(UserTypeRef, {
_id: viaUser,
userGroup: createGroupMembership({
userGroup: createTestEntity(GroupMembershipTypeRef, {
groupInfo: userGroupInfoId,
}),
})
const userGroupInfo = createGroupInfo({
const userGroupInfo = createTestEntity(GroupInfoTypeRef, {
_id: userGroupInfoId,
name: "User name",
mailAddress: "primary@example.com",
mailAddressAliases: [
createMailAddressAlias({
createTestEntity(MailAddressAliasTypeRef, {
mailAddress: "a@a.com",
enabled: true,
}),

View file

@ -1,6 +1,6 @@
import o from "@tutao/otest"
import { MailFacade, phishingMarkerValue, validateMimeTypesForAttachments } from "../../../../../src/api/worker/facades/lazy/MailFacade.js"
import { createMail, createMailAddress, createReportedMailFieldMarker } from "../../../../../src/api/entities/tutanota/TypeRefs.js"
import { MailAddressTypeRef, MailTypeRef, ReportedMailFieldMarkerTypeRef } from "../../../../../src/api/entities/tutanota/TypeRefs.js"
import { MailAuthenticationStatus, ReportedMailFieldType } from "../../../../../src/api/common/TutanotaConstants.js"
import { object } from "testdouble"
import { CryptoFacade } from "../../../../../src/api/worker/crypto/CryptoFacade.js"
@ -13,6 +13,7 @@ import { LoginFacade } from "../../../../../src/api/worker/facades/LoginFacade.j
import { DataFile } from "../../../../../src/api/common/DataFile.js"
import { downcast } from "@tutao/tutanota-utils"
import { ProgrammingError } from "../../../../../src/api/common/error/ProgrammingError.js"
import { createTestEntity } from "../../../TestUtils.js"
o.spec("MailFacade test", function () {
let facade: MailFacade
@ -37,10 +38,10 @@ o.spec("MailFacade test", function () {
o.spec("checkMailForPhishing", function () {
o("not phishing if no markers", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
@ -49,19 +50,19 @@ o.spec("MailFacade test", function () {
})
o("not phishing if no matching markers", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test 2"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_DOMAIN, "example2.com"),
}),
])
@ -70,19 +71,19 @@ o.spec("MailFacade test", function () {
})
o("not phishing if only from domain matches", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test 2"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_DOMAIN, "example.com"),
}),
])
@ -91,19 +92,19 @@ o.spec("MailFacade test", function () {
})
o("not phishing if only subject matches", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_DOMAIN, "example2.com"),
}),
])
@ -112,19 +113,19 @@ o.spec("MailFacade test", function () {
})
o("is phishing if subject and sender domain matches", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_DOMAIN, "example.com"),
}),
])
@ -133,19 +134,19 @@ o.spec("MailFacade test", function () {
})
o("is phishing if subject with whitespaces and sender domain matches", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "\tTest spaces \n",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Testspaces"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_DOMAIN, "example.com"),
}),
])
@ -154,19 +155,19 @@ o.spec("MailFacade test", function () {
})
o("is not phishing if subject and sender domain matches but not authenticated", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.SOFT_FAIL,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_DOMAIN, "example.com"),
}),
])
@ -175,19 +176,19 @@ o.spec("MailFacade test", function () {
})
o("is phishing if subject and sender address matches", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_ADDRESS, "test@example.com"),
}),
])
@ -196,19 +197,19 @@ o.spec("MailFacade test", function () {
})
o("is not phishing if subject and sender address matches but not authenticated", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.SOFT_FAIL,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_ADDRESS, "test@example.com"),
}),
])
@ -217,19 +218,19 @@ o.spec("MailFacade test", function () {
})
o("is phishing if subject and non auth sender domain matches", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.SOFT_FAIL,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_DOMAIN_NON_AUTH, "example.com"),
}),
])
@ -238,19 +239,19 @@ o.spec("MailFacade test", function () {
})
o("is phishing if subject and non auth sender address matches", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.SOFT_FAIL,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.FROM_ADDRESS_NON_AUTH, "test@example.com"),
}),
])
@ -259,19 +260,19 @@ o.spec("MailFacade test", function () {
})
o("is phishing if subject and link matches", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.LINK, "https://example.com"),
}),
])
@ -280,19 +281,19 @@ o.spec("MailFacade test", function () {
})
o("is not phishing if just two links match", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.LINK, "https://example.com"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.LINK, "https://example2.com"),
}),
])
@ -306,19 +307,19 @@ o.spec("MailFacade test", function () {
})
o("is phishing if subject and link domain matches", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.LINK_DOMAIN, "example.com"),
}),
])
@ -327,19 +328,19 @@ o.spec("MailFacade test", function () {
})
o("does not throw on invalid link", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.LINK_DOMAIN, "example.com"),
}),
])
@ -354,16 +355,16 @@ o.spec("MailFacade test", function () {
})
o("is phishing if subject and suspicious link", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
])
@ -372,16 +373,16 @@ o.spec("MailFacade test", function () {
})
o("link is not suspicious if on the same domain", async function () {
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
subject: "Test",
authStatus: MailAuthenticationStatus.AUTHENTICATED,
sender: createMailAddress({
sender: createTestEntity(MailAddressTypeRef, {
name: "a",
address: "test@example.com",
}),
})
facade.phishingMarkersUpdateReceived([
createReportedMailFieldMarker({
createTestEntity(ReportedMailFieldMarkerTypeRef, {
marker: phishingMarkerValue(ReportedMailFieldType.SUBJECT, "Test"),
}),
])

View file

@ -150,7 +150,7 @@ o.spec("OfflineStorage", function () {
o.spec("ElementType", function () {
o("deleteAllOfType", async function () {
const userId = "id1"
const storableUser = createUser({ _id: userId })
const storableUser = createTestEntity(UserTypeRef, { _id: userId })
await storage.init({ userId, databaseKey, timeRangeDays, forceNewDatabase: false })
@ -173,7 +173,7 @@ o.spec("OfflineStorage", function () {
o("deleteAllOfType", async function () {
const listId = "listId1"
const elementId = "id1"
const storableMail = createMail({ _id: [listId, elementId] })
const storableMail = createTestEntity(MailTypeRef, { _id: [listId, elementId] })
await storage.init({ userId: elementId, databaseKey, timeRangeDays, forceNewDatabase: false })
@ -200,7 +200,10 @@ o.spec("OfflineStorage", function () {
o("put, get and delete", async function () {
const archiveId = "archiveId"
const blobElementId = "id1"
const storableMailDetails = createMailDetailsBlob({ _id: [archiveId, blobElementId], details: createTestEntity(MailDetailsTypeRef) })
const storableMailDetails = createTestEntity(MailDetailsBlobTypeRef, {
_id: [archiveId, blobElementId],
details: createTestEntity(MailDetailsTypeRef),
})
await storage.init({ userId, databaseKey, timeRangeDays, forceNewDatabase: false })
@ -223,7 +226,7 @@ o.spec("OfflineStorage", function () {
const archiveId = "archiveId"
const blobElementId = "id1"
const _ownerGroup = "ownerGroup"
const storableMailDetails = createMailDetailsBlob({
const storableMailDetails = createTestEntity(MailDetailsBlobTypeRef, {
_id: [archiveId, blobElementId],
_ownerGroup,
details: createTestEntity(MailDetailsTypeRef),
@ -254,17 +257,21 @@ o.spec("OfflineStorage", function () {
o.beforeEach(async function () {
await storage.init({ userId, databaseKey, timeRangeDays, forceNewDatabase: false })
await insertEntity(createMailFolder({ _id: ["mailFolderList", spamFolderId], mails: spamListId, folderType: MailFolderType.SPAM }))
await insertEntity(createMailFolder({ _id: ["mailFolderList", trashFolderId], mails: trashListId, folderType: MailFolderType.TRASH }))
await insertEntity(
createTestEntity(MailFolderTypeRef, { _id: ["mailFolderList", spamFolderId], mails: spamListId, folderType: MailFolderType.SPAM }),
)
await insertEntity(
createTestEntity(MailFolderTypeRef, { _id: ["mailFolderList", trashFolderId], mails: trashListId, folderType: MailFolderType.TRASH }),
)
})
o("old ranges will be deleted", async function () {
const upper = offsetId(-1)
const lower = offsetId(-2)
const mailDetailsBlobId: IdTuple = ["mailDetailsList", "mailDetailsBlobId"]
await insertEntity(createMailFolder({ _id: ["mailFolderList", "mailFolderId"], mails: listId }))
await insertEntity(createMailDetailsBlob({ _id: mailDetailsBlobId, details: createTestEntity(MailDetailsTypeRef) }))
await insertEntity(createMail({ _id: [listId, "anything"], mailDetails: mailDetailsBlobId }))
await insertEntity(createTestEntity(MailFolderTypeRef, { _id: ["mailFolderList", "mailFolderId"], mails: listId }))
await insertEntity(createTestEntity(MailDetailsBlobTypeRef, { _id: mailDetailsBlobId, details: createTestEntity(MailDetailsTypeRef) }))
await insertEntity(createTestEntity(MailTypeRef, { _id: [listId, "anything"], mailDetails: mailDetailsBlobId }))
await insertRange(MailTypeRef, listId, lower, upper)
// Here we clear the excluded data
@ -281,7 +288,7 @@ o.spec("OfflineStorage", function () {
o("modified ranges will be shrunk", async function () {
const upper = offsetId(2)
const lower = offsetId(-2)
await insertEntity(createMailFolder({ _id: ["mailFolderListId", "mailFolderId"], mails: listId }))
await insertEntity(createTestEntity(MailFolderTypeRef, { _id: ["mailFolderListId", "mailFolderId"], mails: listId }))
await insertRange(MailTypeRef, listId, lower, upper)
// Here we clear the excluded data
@ -295,7 +302,7 @@ o.spec("OfflineStorage", function () {
const upper = offsetId(2)
const lower = offsetId(1)
await insertEntity(createMailFolder({ _id: ["mailFolderList", "mailFolderId"], mails: listId }))
await insertEntity(createTestEntity(MailFolderTypeRef, { _id: ["mailFolderList", "mailFolderId"], mails: listId }))
await insertRange(MailTypeRef, listId, lower, upper)
// Here we clear the excluded data
@ -308,8 +315,8 @@ o.spec("OfflineStorage", function () {
o("complete ranges won't be lost if entities are all newer than cutoff", async function () {
const upper = offsetId(2)
const lower = GENERATED_MIN_ID
const mail = createMail({ _id: [listId, offsetId(1)] })
const mailFolder = createMailFolder({ _id: ["mailFolderList", "folderId"], mails: listId })
const mail = createTestEntity(MailTypeRef, { _id: [listId, offsetId(1)] })
const mailFolder = createTestEntity(MailFolderTypeRef, { _id: ["mailFolderList", "folderId"], mails: listId })
await insertEntity(mailFolder)
await insertEntity(mail)
await insertRange(MailTypeRef, listId, lower, upper)
@ -331,14 +338,14 @@ o.spec("OfflineStorage", function () {
const trashMailBodyId = "trashMailBodyId"
const spamMailId = offsetId(2)
const spamMail = createMail({ _id: [spamListId, spamMailId], body: spamMailBodyId })
const spamMail = createTestEntity(MailTypeRef, { _id: [spamListId, spamMailId], body: spamMailBodyId })
const trashMailId = offsetId(2)
const trashMail = createMail({ _id: [trashListId, trashMailId], body: trashMailBodyId })
const trashMail = createTestEntity(MailTypeRef, { _id: [trashListId, trashMailId], body: trashMailBodyId })
await insertEntity(spamMail)
await insertEntity(trashMail)
await insertEntity(createMailBody({ _id: spamMailBodyId }))
await insertEntity(createMailBody({ _id: trashMailBodyId }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: spamMailBodyId }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: trashMailBodyId }))
// Here we clear the excluded data
await storage.clearExcludedData(timeRangeDays, userId)
@ -359,14 +366,14 @@ o.spec("OfflineStorage", function () {
const trashSubfolderMailBodyId = "trashSubfolderMailBodyId"
const spamMailId = offsetId(2)
const spamMail = createMail({ _id: [spamListId, spamMailId], body: spamMailBodyId })
const spamMail = createTestEntity(MailTypeRef, { _id: [spamListId, spamMailId], body: spamMailBodyId })
const trashMailId = offsetId(2)
const trashMail = createMail({ _id: [trashListId, trashMailId], body: trashMailBodyId })
const trashMail = createTestEntity(MailTypeRef, { _id: [trashListId, trashMailId], body: trashMailBodyId })
const trashSubfolderMailId = offsetId(2)
const trashSubfolderMail = createMail({ _id: [trashSubfolderListId, trashSubfolderMailId], body: trashSubfolderMailBodyId })
const trashSubfolderMail = createTestEntity(MailTypeRef, { _id: [trashSubfolderListId, trashSubfolderMailId], body: trashSubfolderMailBodyId })
await insertEntity(
createMailFolder({
createTestEntity(MailFolderTypeRef, {
_id: ["mailFolderList", trashSubfolderId],
parentFolder: ["mailFolderList", trashFolderId],
mails: trashSubfolderListId,
@ -376,9 +383,9 @@ o.spec("OfflineStorage", function () {
await insertEntity(spamMail)
await insertEntity(trashMail)
await insertEntity(trashSubfolderMail)
await insertEntity(createMailBody({ _id: spamMailBodyId }))
await insertEntity(createMailBody({ _id: trashMailBodyId }))
await insertEntity(createMailBody({ _id: trashSubfolderMailBodyId }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: spamMailBodyId }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: trashMailBodyId }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: trashSubfolderMailBodyId }))
// Here we clear the excluded data
await storage.clearExcludedData(timeRangeDays, userId)
@ -397,15 +404,15 @@ o.spec("OfflineStorage", function () {
const spamMailId = offsetId(2)
const trashMailId = offsetId(2)
const spamMail = createMail({ _id: [spamListId, spamMailId], mailDetails: spamDetailsId })
const trashMail = createMail({ _id: [trashListId, trashMailId], mailDetails: trashDetailsId })
const spamMail = createTestEntity(MailTypeRef, { _id: [spamListId, spamMailId], mailDetails: spamDetailsId })
const trashMail = createTestEntity(MailTypeRef, { _id: [trashListId, trashMailId], mailDetails: trashDetailsId })
await storage.init({ userId, databaseKey, timeRangeDays, forceNewDatabase: false })
await insertEntity(spamMail)
await insertEntity(trashMail)
await insertEntity(createMailDetailsBlob({ _id: spamDetailsId, details: createTestEntity(MailDetailsTypeRef) }))
await insertEntity(createMailDetailsBlob({ _id: trashDetailsId, details: createTestEntity(MailDetailsTypeRef) }))
await insertEntity(createTestEntity(MailDetailsBlobTypeRef, { _id: spamDetailsId, details: createTestEntity(MailDetailsTypeRef) }))
await insertEntity(createTestEntity(MailDetailsBlobTypeRef, { _id: trashDetailsId, details: createTestEntity(MailDetailsTypeRef) }))
// Here we clear the excluded data
await storage.clearExcludedData(timeRangeDays, userId)
@ -423,14 +430,16 @@ o.spec("OfflineStorage", function () {
const beforeMailBodyId = "beforeMailBodyId"
const afterMailBodyId = "afterMailBodyId"
const mailBefore = createMail({ _id: [inboxMailList, offsetId(-2)], body: beforeMailBodyId })
const mailAfter = createMail({ _id: [inboxMailList, offsetId(2)], body: afterMailBodyId })
const mailBefore = createTestEntity(MailTypeRef, { _id: [inboxMailList, offsetId(-2)], body: beforeMailBodyId })
const mailAfter = createTestEntity(MailTypeRef, { _id: [inboxMailList, offsetId(2)], body: afterMailBodyId })
await insertEntity(createMailFolder({ _id: ["mailFolderList", "folderId"], mails: inboxMailList, folderType: MailFolderType.INBOX }))
await insertEntity(
createTestEntity(MailFolderTypeRef, { _id: ["mailFolderList", "folderId"], mails: inboxMailList, folderType: MailFolderType.INBOX }),
)
await insertEntity(mailBefore)
await insertEntity(mailAfter)
await insertEntity(createMailBody({ _id: beforeMailBodyId }))
await insertEntity(createMailBody({ _id: afterMailBodyId }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: beforeMailBodyId }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: afterMailBodyId }))
// Here we clear the excluded data
await storage.clearExcludedData(timeRangeDays, userId)
@ -446,14 +455,16 @@ o.spec("OfflineStorage", function () {
const mailBodyId1 = "mailBodyId1"
const mailBodyId2 = "afterMailBodyId"
const mail1 = createMail({ _id: [inboxMailList, offsetId(-2)], body: mailBodyId1 })
const mail2 = createMail({ _id: [inboxMailList, offsetId(-3)], body: mailBodyId2 })
const mail1 = createTestEntity(MailTypeRef, { _id: [inboxMailList, offsetId(-2)], body: mailBodyId1 })
const mail2 = createTestEntity(MailTypeRef, { _id: [inboxMailList, offsetId(-3)], body: mailBodyId2 })
await insertEntity(createMailFolder({ _id: ["mailFolderList", "folderId"], mails: inboxMailList, folderType: MailFolderType.INBOX }))
await insertEntity(
createTestEntity(MailFolderTypeRef, { _id: ["mailFolderList", "folderId"], mails: inboxMailList, folderType: MailFolderType.INBOX }),
)
await insertEntity(mail1)
await insertEntity(mail2)
await insertEntity(createMailBody({ _id: mailBodyId1 }))
await insertEntity(createMailBody({ _id: mailBodyId2 }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: mailBodyId1 }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: mailBodyId2 }))
// Here we clear the excluded data
await storage.clearExcludedData(timeRangeDays, userId)
@ -468,18 +479,20 @@ o.spec("OfflineStorage", function () {
const afterMailBodyId = "afterMailBodyId"
const fileListId = "fileListId"
const fileBefore = createFile({ _id: [fileListId, "fileBefore"] })
const fileAfter = createFile({ _id: [fileListId, "fileAfter"] })
const mailBefore = createMail({ _id: [inboxMailList, offsetId(-2)], body: beforeMailBodyId, attachments: [fileBefore._id] })
const mailAfter = createMail({ _id: [inboxMailList, offsetId(2)], body: afterMailBodyId, attachments: [fileAfter._id] })
const fileBefore = createTestEntity(FileTypeRef, { _id: [fileListId, "fileBefore"] })
const fileAfter = createTestEntity(FileTypeRef, { _id: [fileListId, "fileAfter"] })
const mailBefore = createTestEntity(MailTypeRef, { _id: [inboxMailList, offsetId(-2)], body: beforeMailBodyId, attachments: [fileBefore._id] })
const mailAfter = createTestEntity(MailTypeRef, { _id: [inboxMailList, offsetId(2)], body: afterMailBodyId, attachments: [fileAfter._id] })
await insertEntity(createMailFolder({ _id: ["mailFolderList", "folderId"], mails: inboxMailList, folderType: MailFolderType.INBOX }))
await insertEntity(
createTestEntity(MailFolderTypeRef, { _id: ["mailFolderList", "folderId"], mails: inboxMailList, folderType: MailFolderType.INBOX }),
)
await insertEntity(mailBefore)
await insertEntity(mailAfter)
await insertEntity(fileBefore)
await insertEntity(fileAfter)
await insertEntity(createMailBody({ _id: beforeMailBodyId }))
await insertEntity(createMailBody({ _id: afterMailBodyId }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: beforeMailBodyId }))
await insertEntity(createTestEntity(MailBodyTypeRef, { _id: afterMailBodyId }))
// Here we clear the excluded data
await storage.clearExcludedData(timeRangeDays, userId)
@ -498,14 +511,14 @@ o.spec("OfflineStorage", function () {
const mailId = idGenerator.getNext()
const bodyId = idGenerator.getNext()
mails.push(
createMail({
createTestEntity(MailTypeRef, {
_id: [listId, mailId],
subject: getSubject(i),
body: bodyId,
}),
)
mailBodies.push(
createMailBody({
createTestEntity(MailBodyTypeRef, {
_id: bodyId,
text: getBody(i),
}),
@ -520,7 +533,7 @@ o.spec("OfflineStorage", function () {
const newIds = new IdGenerator(offsetId(5))
const inboxListId = oldIds.getNext()
const inboxFolder = createMailFolder({
const inboxFolder = createTestEntity(MailFolderTypeRef, {
_id: [userId, oldIds.getNext()],
mails: inboxListId,
folderType: MailFolderType.INBOX,
@ -542,7 +555,7 @@ o.spec("OfflineStorage", function () {
)
const trashListId = oldIds.getNext()
const trashFolder = createMailFolder({
const trashFolder = createTestEntity(MailFolderTypeRef, {
_id: [userId, oldIds.getNext()],
mails: trashListId,
folderType: MailFolderType.TRASH,
@ -556,7 +569,7 @@ o.spec("OfflineStorage", function () {
)
const spamListId = oldIds.getNext()
const spamFolder = createMailFolder({
const spamFolder = createTestEntity(MailFolderTypeRef, {
_id: [userId, oldIds.getNext()],
mails: spamListId,
folderType: MailFolderType.SPAM,

View file

@ -7,6 +7,7 @@ import { EntityRestClient } from "../../../../../src/api/worker/rest/EntityRestC
import { LateInitializedCacheStorageImpl } from "../../../../../src/api/worker/rest/CacheStorageProxy.js"
import { CUSTOM_MAX_ID, CUSTOM_MIN_ID, LOAD_MULTIPLE_LIMIT } from "../../../../../src/api/common/utils/EntityUtils.js"
import { numberRange } from "@tutao/tutanota-utils"
import { createTestEntity } from "../../../TestUtils.js"
o.spec("Custom calendar events handler", function () {
const entityRestClientMock = instance(EntityRestClient)
@ -15,11 +16,11 @@ o.spec("Custom calendar events handler", function () {
const listId = "listId"
let timestamp = Date.now()
const ids = [0, 1, 2, 3, 4, 5, 6].map((n) => createEventElementId(timestamp, n))
const allList = [0, 1, 2, 3, 4, 5, 6].map((n) => createCalendarEvent({ _id: [listId, ids[n]] }))
const allList = [0, 1, 2, 3, 4, 5, 6].map((n) => createTestEntity(CalendarEventTypeRef, { _id: [listId, ids[n]] }))
const bigListId = "bigListId"
const bigListIds = numberRange(0, 299).map((n) => createEventElementId(timestamp, n))
const bigList = numberRange(0, 299).map((n) => createCalendarEvent({ _id: [bigListId, bigListIds[n]] }))
const bigList = numberRange(0, 299).map((n) => createTestEntity(CalendarEventTypeRef, { _id: [bigListId, bigListIds[n]] }))
const toElementId = (e) => e._id[1]
o.spec("Load elements from cache", function () {

View file

@ -15,6 +15,7 @@ import {
} from "../../../../../src/api/common/utils/EntityUtils.js"
import { arrayOf, clone, downcast, isSameTypeRef, neverNull, TypeRef } from "@tutao/tutanota-utils"
import {
BucketKeyTypeRef,
createBucketKey,
createCustomer,
createEntityUpdate,
@ -28,6 +29,9 @@ import {
EntityUpdate,
EntityUpdateTypeRef,
ExternalUserReferenceTypeRef,
GroupMembershipTypeRef,
GroupRootTypeRef,
InstanceSessionKeyTypeRef,
PermissionTypeRef,
UserTypeRef,
} from "../../../../../src/api/entities/sys/TypeRefs.js"
@ -187,8 +191,8 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
const calendarEventIds = [0, 1, 2, 3, 4, 5, 6].map((n) => createEventElementId(timestamp, n))
o("writes batch meta on entity update", async function () {
const contact1 = createContact({ _id: [contactListId1, id1] })
const contact2 = createContact({ _id: [contactListId1, id2] })
const contact1 = createTestEntity(ContactTypeRef, { _id: [contactListId1, id1] })
const contact2 = createTestEntity(ContactTypeRef, { _id: [contactListId1, id2] })
const batch = [
createUpdate(ContactTypeRef, contactListId1, id1, OperationType.CREATE),
@ -215,8 +219,8 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
//when using offline calendar ids are always in cache range
})
o("entity events received should call loadMultiple when receiving updates from a postMultiple", async function () {
const contact1 = createContact({ _id: [contactListId1, id1] })
const contact2 = createContact({ _id: [contactListId1, id2] })
const contact1 = createTestEntity(ContactTypeRef, { _id: [contactListId1, id1] })
const contact2 = createTestEntity(ContactTypeRef, { _id: [contactListId1, id2] })
const batch = [
createUpdate(ContactTypeRef, contactListId1, id1, OperationType.CREATE),
@ -240,8 +244,8 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
if (name === "offline") {
// in the other case storage is an EphemeralCache which doesn't use custom handlers or caches calendar events.
o("entity events received should call loadMultiple when receiving updates from a postMultiple with CustomCacheHandler", async function () {
const event1 = createCalendarEvent({ _id: [calendarEventListId, calendarEventIds[0]] })
const event2 = createCalendarEvent({ _id: [calendarEventListId, calendarEventIds[1]] })
const event1 = createTestEntity(CalendarEventTypeRef, { _id: [calendarEventListId, calendarEventIds[0]] })
const event2 = createTestEntity(CalendarEventTypeRef, { _id: [calendarEventListId, calendarEventIds[1]] })
// We only consider events to be in the range if we do actually have correct range
await storage.setNewRangeForList(CalendarEventTypeRef, calendarEventListId, CUSTOM_MIN_ID, CUSTOM_MAX_ID)
@ -282,14 +286,14 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
if (isSameTypeRef(typeRef, ContactTypeRef)) {
o(elementId).equals(id2)
return Promise.resolve(
createContact({
createTestEntity(ContactTypeRef, {
_id: [neverNull(listId), elementId],
}),
)
} else if (isSameTypeRef(typeRef, CustomerTypeRef)) {
o(["id5", "id6", "id7"].includes(elementId)).equals(true)
return Promise.resolve(
createCustomer({
createTestEntity(CustomerTypeRef, {
_id: elementId,
}),
)
@ -301,30 +305,30 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
if (listId === contactListId1) {
o(ids).deepEquals(["id1", "id2"])
return Promise.resolve([
createContact({
createTestEntity(ContactTypeRef, {
_id: [listId, id1],
}),
createContact({
createTestEntity(ContactTypeRef, {
_id: [listId, id2],
}),
])
} else if (listId === calendarEventListId) {
o(ids).deepEquals([calendarEventIds[0], calendarEventIds[1]])
return Promise.resolve([
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: [calendarEventListId, calendarEventIds[0]],
}),
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: [calendarEventListId, calendarEventIds[1]],
}),
])
} else if (listId === contactListId2) {
o(ids).deepEquals(["id3", "id4"])
return Promise.resolve([
createContact({
createTestEntity(ContactTypeRef, {
_id: [listId, "id3"],
}),
createContact({
createTestEntity(ContactTypeRef, {
_id: [listId, "id4"],
}),
])
@ -384,10 +388,10 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
if (listId === contactListId1) {
o(ids).deepEquals(["id1", "id2"])
return Promise.resolve([
createContact({
createTestEntity(ContactTypeRef, {
_id: [listId, id1],
}),
createContact({
createTestEntity(ContactTypeRef, {
_id: [listId, id2],
}),
])
@ -432,7 +436,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
if (isSameTypeRef(typeRef, ContactTypeRef)) {
if (listId === contactListId1) {
o(ids).deepEquals(["id1", "id2"])
return Promise.resolve([createContact({ _id: [listId, id1] })])
return Promise.resolve([createTestEntity(ContactTypeRef, { _id: [listId, id1] })])
}
}
throw new Error("should not be reached")
@ -465,14 +469,14 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
if (listId === contactListId1) {
o(ids).deepEquals(["id1"])
return Promise.resolve([
createContact({
createTestEntity(ContactTypeRef, {
_id: [listId, id1],
}),
])
} else if (listId === contactListId2) {
o(ids).deepEquals(["id4"])
return Promise.resolve([
createContact({
createTestEntity(ContactTypeRef, {
_id: [listId, "id4"],
}),
])
@ -508,7 +512,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
if (listId === contactListId1) {
o(ids).deepEquals(["id1"])
return Promise.resolve([
createContact({
createTestEntity(ContactTypeRef, {
_id: [listId, id1],
}),
])
@ -620,9 +624,9 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
})
o("Mail should not be loaded when a move event is received - update bucket key", async function () {
const instance = createMailInstance("listId1", "id1", "henlo")
instance.bucketKey = createBucketKey({
instance.bucketKey = createTestEntity(BucketKeyTypeRef, {
bucketEncSessionKeys: [
createInstanceSessionKey({
createTestEntity(InstanceSessionKeyTypeRef, {
instanceList: "listId1",
instanceId: getElementId(instance),
}),
@ -723,7 +727,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
})
o("delete Mail deletes MailDetailsBlob", async function () {
const mailDetailsBlob = createMailDetailsBlob({ _id: ["archiveId", "blobId"] })
const mailDetailsBlob = createTestEntity(MailDetailsBlobTypeRef, { _id: ["archiveId", "blobId"] })
const mail = createMailInstance("listId1", "id1", "mail 1")
mail.mailDetails = mailDetailsBlob._id
@ -780,14 +784,14 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
o("no membership change does not delete an entity and lastUpdateBatchIdPerGroup", async function () {
const userId = "userId"
const calendarGroupId = "calendarGroupId"
const initialUser = createUser({
const initialUser = createTestEntity(UserTypeRef, {
_id: userId,
memberships: [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "mailShipId",
groupType: GroupType.Mail,
}),
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "calendarShipId",
group: calendarGroupId,
groupType: GroupType.Calendar,
@ -801,7 +805,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
await storage.put(initialUser)
const eventId: IdTuple = ["eventListId", "eventId"]
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
_id: eventId,
_ownerGroup: calendarGroupId,
})
@ -819,14 +823,14 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
o("membership change deletes an element entity and lastUpdateBatchIdPerGroup", async function () {
const userId = "userId"
const calendarGroupId = "calendarGroupId"
const initialUser = createUser({
const initialUser = createTestEntity(UserTypeRef, {
_id: userId,
memberships: [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "mailShipId",
groupType: GroupType.Mail,
}),
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "calendarShipId",
group: calendarGroupId,
groupType: GroupType.Calendar,
@ -836,10 +840,10 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
await storage.put(initialUser)
const updatedUser = createUser({
const updatedUser = createTestEntity(UserTypeRef, {
_id: userId,
memberships: [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "mailShipId",
groupType: GroupType.Mail,
}),
@ -850,7 +854,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
when(entityRestClient.load(UserTypeRef, userId)).thenResolve(updatedUser)
const groupRootId = "groupRootId"
const groupRoot = createGroupRoot({
const groupRoot = createTestEntity(GroupRootTypeRef, {
_id: groupRootId,
_ownerGroup: calendarGroupId,
})
@ -868,14 +872,14 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
o("membership change deletes a list entity and lastUpdateBatchIdPerGroup", async function () {
const userId = "userId"
const calendarGroupId = "calendarGroupId"
const initialUser = createUser({
const initialUser = createTestEntity(UserTypeRef, {
_id: userId,
memberships: [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "mailShipId",
groupType: GroupType.Mail,
}),
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "calendarShipId",
group: calendarGroupId,
groupType: GroupType.Calendar,
@ -885,10 +889,10 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
await storage.put(initialUser)
const updatedUser = createUser({
const updatedUser = createTestEntity(UserTypeRef, {
_id: userId,
memberships: [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "mailShipId",
groupType: GroupType.Mail,
}),
@ -899,7 +903,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
when(entityRestClient.load(UserTypeRef, userId)).thenResolve(updatedUser)
const eventId: IdTuple = ["eventListId", "eventId"]
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
_id: eventId,
_ownerGroup: calendarGroupId,
})
@ -919,14 +923,14 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
o("membership change but for another user does nothing", async function () {
const userId = "userId"
const calendarGroupId = "calendarGroupId"
const initialUser = createUser({
const initialUser = createTestEntity(UserTypeRef, {
_id: userId,
memberships: [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "mailShipId",
groupType: GroupType.Mail,
}),
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "calendarShipId",
group: calendarGroupId,
groupType: GroupType.Calendar,
@ -936,10 +940,10 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
await storage.put(initialUser)
const updatedUser = createUser({
const updatedUser = createTestEntity(UserTypeRef, {
_id: userId,
memberships: [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: "mailShipId",
groupType: GroupType.Mail,
}),
@ -950,7 +954,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
when(entityRestClient.load(UserTypeRef, userId)).thenResolve(updatedUser)
const eventId: IdTuple = ["eventListId", "eventId"]
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
_id: eventId,
_ownerGroup: calendarGroupId,
})
@ -1514,7 +1518,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
})
o("load passes same parameters to entityRestClient", async function () {
const contactId: IdTuple = [createId("0"), createId("1")]
const contact = createContact({
const contact = createTestEntity(ContactTypeRef, {
_id: contactId,
firstName: "greg",
})
@ -1544,7 +1548,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
})
o("single entity is cached after being loaded", async function () {
const contactId: IdTuple = [createId("0"), createId("1")]
const contactOnTheServer = createContact({
const contactOnTheServer = createTestEntity(ContactTypeRef, {
_id: contactId,
firstName: "greg",
})
@ -1567,12 +1571,12 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
o("A new range request for a nonexistent range should initialize that range", async function () {
const loadRange = spy(function (typeRef, listId, ...an) {
return [
createContact({ _id: [listId, createId("1")] }),
createContact({ _id: [listId, createId("2")] }),
createContact({ _id: [listId, createId("3")] }),
createContact({ _id: [listId, createId("4")] }),
createContact({ _id: [listId, createId("5")] }),
createContact({ _id: [listId, createId("6")] }),
createTestEntity(ContactTypeRef, { _id: [listId, createId("1")] }),
createTestEntity(ContactTypeRef, { _id: [listId, createId("2")] }),
createTestEntity(ContactTypeRef, { _id: [listId, createId("3")] }),
createTestEntity(ContactTypeRef, { _id: [listId, createId("4")] }),
createTestEntity(ContactTypeRef, { _id: [listId, createId("5")] }),
createTestEntity(ContactTypeRef, { _id: [listId, createId("6")] }),
]
})
@ -1587,7 +1591,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
o("single entity is not cached if it is an ignored entity", async function () {
const permissionId: IdTuple = [createId("0"), createId("1")]
const permissionOnTheServer = createPermission({
const permissionOnTheServer = createTestEntity(PermissionTypeRef, {
_id: permissionId,
})
const client = downcast<EntityRestClient>({
@ -1605,7 +1609,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
o.spec("no user id", function () {
o("get", async function () {
userId = null
entityRestClient.load = spy(async () => createContact({ _id: ["listId", "id"] })) as EntityRestClient["load"]
entityRestClient.load = spy(async () => createTestEntity(ContactTypeRef, { _id: ["listId", "id"] })) as EntityRestClient["load"]
await cache.load(ContactTypeRef, ["listId", "id"])
o(entityRestClient.load.callCount).equals(1)
})
@ -1613,7 +1617,7 @@ export function testEntityRestCache(name: string, getStorage: (userId: Id) => Pr
o("put", async function () {
userId = null
entityRestClient.setup = spy(async () => "id")
await cache.setup("listId", createContact({ _id: ["listId", "id"] }))
await cache.setup("listId", createTestEntity(ContactTypeRef, { _id: ["listId", "id"] }))
o(entityRestClient.setup.callCount).equals(1)
})
})

View file

@ -19,7 +19,12 @@ import tutanotaModelInfo from "../../../../../src/api/entities/tutanota/ModelInf
import sysModelInfo from "../../../../../src/api/entities/sys/ModelInfo.js"
import { AuthDataProvider } from "../../../../../src/api/worker/facades/UserFacade.js"
import { LoginIncompleteError } from "../../../../../src/api/common/error/LoginIncompleteError.js"
import { createBlobServerAccessInfo, createBlobServerUrl } from "../../../../../src/api/entities/storage/TypeRefs.js"
import {
BlobServerAccessInfoTypeRef,
BlobServerUrlTypeRef,
createBlobServerAccessInfo,
createBlobServerUrl,
} from "../../../../../src/api/entities/storage/TypeRefs.js"
import { Mapper, ofClass } from "@tutao/tutanota-utils"
import { ProgrammingError } from "../../../../../src/api/common/error/ProgrammingError.js"
import { BlobAccessTokenFacade } from "../../../../../src/api/worker/facades/BlobAccessTokenFacade.js"
@ -57,7 +62,7 @@ const countFrom = (start, count) => createArrayOf(count, (idx) => String(idx + s
function contacts(count) {
const contactFactory = (idx) =>
createContact({
createTestEntity(ContactTypeRef, {
firstName: `Contact${idx}`,
})
@ -343,9 +348,9 @@ o.spec("EntityRestClient", async function () {
const firstServer = "firstServer"
const blobAccessToken = "123"
let blobServerAccessInfo = createBlobServerAccessInfo({
let blobServerAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, {
blobAccessToken,
servers: [createBlobServerUrl({ url: firstServer }), createBlobServerUrl({ url: "otherServer" })],
servers: [createTestEntity(BlobServerUrlTypeRef, { url: firstServer }), createTestEntity(BlobServerUrlTypeRef, { url: "otherServer" })],
})
when(blobAccessTokenFacade.requestReadTokenArchive(archiveId)).thenResolve(blobServerAccessInfo)
@ -399,9 +404,9 @@ o.spec("EntityRestClient", async function () {
const blobAccessToken = "123"
const otherServer = "otherServer"
const blobServerAccessInfo = createBlobServerAccessInfo({
const blobServerAccessInfo = createTestEntity(BlobServerAccessInfoTypeRef, {
blobAccessToken,
servers: [createBlobServerUrl({ url: firstServer }), createBlobServerUrl({ url: otherServer })],
servers: [createTestEntity(BlobServerUrlTypeRef, { url: firstServer }), createTestEntity(BlobServerUrlTypeRef, { url: otherServer })],
})
when(blobAccessTokenFacade.requestReadTokenArchive(archiveId)).thenResolve(blobServerAccessInfo)
@ -793,7 +798,7 @@ o.spec("EntityRestClient", async function () {
o.spec("Update", function () {
o("Update entity", async function () {
const { version } = await resolveTypeReference(CustomerTypeRef)
const newCustomer = createCustomer({
const newCustomer = createTestEntity(CustomerTypeRef, {
_id: "id",
})
when(
@ -815,7 +820,7 @@ o.spec("EntityRestClient", async function () {
o("when ownerKey is passed it is used instead for session key resolution", async function () {
const typeModel = await resolveTypeReference(CustomerTypeRef)
const version = typeModel.version
const newCustomer = createCustomer({
const newCustomer = createTestEntity(CustomerTypeRef, {
_id: "id",
})
when(
@ -840,7 +845,7 @@ o.spec("EntityRestClient", async function () {
o("Delete entity", async function () {
const { version } = await resolveTypeReference(CustomerTypeRef)
const id = "id"
const newCustomer = createCustomer({
const newCustomer = createTestEntity(CustomerTypeRef, {
_id: id,
})
when(
@ -855,7 +860,7 @@ o.spec("EntityRestClient", async function () {
o.spec("tryServers", function () {
o("tryServers successful", async function () {
let servers = [createBlobServerUrl({ url: "w1" }), createBlobServerUrl({ url: "w2" })]
let servers = [createTestEntity(BlobServerUrlTypeRef, { url: "w1" }), createTestEntity(BlobServerUrlTypeRef, { url: "w2" })]
const mapperMock = func<Mapper<string, object>>()
const expectedResult = { response: "response-from-server" }
when(mapperMock(anything(), anything())).thenResolve(expectedResult)
@ -866,7 +871,7 @@ o.spec("EntityRestClient", async function () {
})
o("tryServers error", async function () {
let servers = [createBlobServerUrl({ url: "w1" }), createBlobServerUrl({ url: "w2" })]
let servers = [createTestEntity(BlobServerUrlTypeRef, { url: "w1" }), createTestEntity(BlobServerUrlTypeRef, { url: "w2" })]
const mapperMock = func<Mapper<string, object>>()
when(mapperMock("w1", 0)).thenReject(new ProgrammingError("test"))
const e = await assertThrows(ProgrammingError, () => tryServers(servers, mapperMock, "error"))
@ -875,7 +880,7 @@ o.spec("EntityRestClient", async function () {
})
o("tryServers ConnectionError and successful response", async function () {
let servers = [createBlobServerUrl({ url: "w1" }), createBlobServerUrl({ url: "w2" })]
let servers = [createTestEntity(BlobServerUrlTypeRef, { url: "w1" }), createTestEntity(BlobServerUrlTypeRef, { url: "w2" })]
const mapperMock = func<Mapper<string, object>>()
const expectedResult = { response: "response-from-server" }
when(mapperMock("w1", 0)).thenReject(new ConnectionError("test"))
@ -886,7 +891,7 @@ o.spec("EntityRestClient", async function () {
})
o("tryServers multiple ConnectionError", async function () {
let servers = [createBlobServerUrl({ url: "w1" }), createBlobServerUrl({ url: "w2" })]
let servers = [createTestEntity(BlobServerUrlTypeRef, { url: "w1" }), createTestEntity(BlobServerUrlTypeRef, { url: "w2" })]
const mapperMock = func<Mapper<string, object>>()
when(mapperMock("w1", 0)).thenReject(new ConnectionError("test"))
when(mapperMock("w2", 1)).thenReject(new ConnectionError("test"))

View file

@ -13,7 +13,10 @@ o.spec("EphemeralCacheStorageTest", function () {
o.spec("BlobElementType", function () {
o("cache roundtrip: put, get, delete", async function () {
storage.init({ userId })
const storableMailDetailsBlob = createMailDetailsBlob({ _id: [archiveId, blobElementId], details: createTestEntity(MailDetailsTypeRef) })
const storableMailDetailsBlob = createTestEntity(MailDetailsBlobTypeRef, {
_id: [archiveId, blobElementId],
details: createTestEntity(MailDetailsTypeRef),
})
let mailDetailsBlob = await storage.get(MailDetailsBlobTypeRef, archiveId, blobElementId)
o(mailDetailsBlob).equals(null)
@ -31,7 +34,7 @@ o.spec("EphemeralCacheStorageTest", function () {
o("cache roundtrip: put, get, deleteAllOwnedBy", async function () {
const _ownerGroup = "owenerGroup"
storage.init({ userId })
const storableMailDetailsBlob = createMailDetailsBlob({
const storableMailDetailsBlob = createTestEntity(MailDetailsBlobTypeRef, {
_id: [archiveId, blobElementId],
_ownerGroup,
details: createTestEntity(MailDetailsTypeRef),

View file

@ -5,19 +5,14 @@ import { InstanceMapper } from "../../../../../src/api/worker/crypto/InstanceMap
import { CryptoFacade } from "../../../../../src/api/worker/crypto/CryptoFacade.js"
import { matchers, object, when } from "testdouble"
import { DeleteService, GetService, PostService, PutService } from "../../../../../src/api/common/ServiceRequest.js"
import {
AlarmServicePostTypeRef,
createGiftCardCreateData,
createSaltData,
GiftCardCreateDataTypeRef,
SaltDataTypeRef,
} from "../../../../../src/api/entities/sys/TypeRefs.js"
import { AlarmServicePostTypeRef, GiftCardCreateDataTypeRef, SaltDataTypeRef } from "../../../../../src/api/entities/sys/TypeRefs.js"
import { HttpMethod, MediaType, resolveTypeReference } from "../../../../../src/api/common/EntityFunctions.js"
import { deepEqual } from "@tutao/tutanota-utils"
import { assertThrows, verify } from "@tutao/tutanota-test-utils"
import { ProgrammingError } from "../../../../../src/api/common/error/ProgrammingError"
import { AuthDataProvider } from "../../../../../src/api/worker/facades/UserFacade"
import { LoginIncompleteError } from "../../../../../src/api/common/error/LoginIncompleteError.js"
import { createTestEntity } from "../../../TestUtils.js"
const { anything } = matchers
@ -68,7 +63,7 @@ o.spec("ServiceExecutor", function () {
return: null,
},
}
const data = createSaltData({ mailAddress: "test" })
const data = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.encryptAndMapToLiteral(saltTypeModel, data, null)).thenResolve(literal)
@ -95,7 +90,7 @@ o.spec("ServiceExecutor", function () {
return: SaltDataTypeRef,
},
}
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.decryptAndMapToInstance(saltTypeModel, literal, null)).thenResolve(returnData)
@ -121,7 +116,7 @@ o.spec("ServiceExecutor", function () {
return: AlarmServicePostTypeRef,
},
}
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(AlarmServicePostTypeRef)
when(instanceMapper.decryptAndMapToInstance(saltTypeModel, literal, null)).thenResolve(returnData)
@ -162,7 +157,7 @@ o.spec("ServiceExecutor", function () {
}
const sessionKey = [1, 2, 3]
fullyLoggedIn = false
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(AlarmServicePostTypeRef)
when(instanceMapper.decryptAndMapToInstance(saltTypeModel, literal, sessionKey)).thenResolve(returnData)
@ -190,7 +185,7 @@ o.spec("ServiceExecutor", function () {
},
}
fullyLoggedIn = false
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.decryptAndMapToInstance(saltTypeModel, literal, null)).thenResolve(returnData)
@ -219,7 +214,7 @@ o.spec("ServiceExecutor", function () {
return: null,
},
}
const data = createSaltData({ mailAddress: "test" })
const data = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.encryptAndMapToLiteral(saltTypeModel, data, null)).thenResolve(literal)
@ -246,7 +241,7 @@ o.spec("ServiceExecutor", function () {
return: SaltDataTypeRef,
},
}
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.decryptAndMapToInstance(saltTypeModel, literal, null)).thenResolve(returnData)
@ -287,7 +282,7 @@ o.spec("ServiceExecutor", function () {
}
const sessionKey = [1, 2, 3]
fullyLoggedIn = false
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(AlarmServicePostTypeRef)
when(instanceMapper.decryptAndMapToInstance(saltTypeModel, literal, sessionKey)).thenResolve(returnData)
@ -316,7 +311,7 @@ o.spec("ServiceExecutor", function () {
return: null,
},
}
const data = createSaltData({ mailAddress: "test" })
const data = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.encryptAndMapToLiteral(saltTypeModel, data, null)).thenResolve(literal)
@ -343,7 +338,7 @@ o.spec("ServiceExecutor", function () {
return: SaltDataTypeRef,
},
}
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.decryptAndMapToInstance(saltTypeModel, literal, null)).thenResolve(returnData)
@ -384,7 +379,7 @@ o.spec("ServiceExecutor", function () {
return: null,
},
}
const data = createSaltData({ mailAddress: "test" })
const data = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.encryptAndMapToLiteral(saltTypeModel, data, null)).thenResolve(literal)
@ -411,7 +406,7 @@ o.spec("ServiceExecutor", function () {
return: SaltDataTypeRef,
},
}
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.decryptAndMapToInstance(saltTypeModel, literal, null)).thenResolve(returnData)
@ -453,7 +448,7 @@ o.spec("ServiceExecutor", function () {
return: null,
},
}
const data = createSaltData({ mailAddress: "test" })
const data = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const query = Object.freeze({ myQueryParam: "2" })
when(instanceMapper.encryptAndMapToLiteral(anything(), anything(), anything())).thenResolve({})
respondWith(undefined)
@ -478,7 +473,7 @@ o.spec("ServiceExecutor", function () {
return: null,
},
}
const data = createSaltData({ mailAddress: "test" })
const data = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const headers = Object.freeze({ myHeader: "2" })
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
when(instanceMapper.encryptAndMapToLiteral(anything(), anything(), anything())).thenResolve({})
@ -505,7 +500,7 @@ o.spec("ServiceExecutor", function () {
return: null,
},
}
const data = createSaltData({ mailAddress: "test" })
const data = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const accessToken = "myAccessToken"
authHeaders = { accessToken }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
@ -534,7 +529,7 @@ o.spec("ServiceExecutor", function () {
return: SaltDataTypeRef,
},
}
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
const sessionKey = [1, 2, 3]
@ -563,7 +558,7 @@ o.spec("ServiceExecutor", function () {
return: SaltDataTypeRef,
},
}
const returnData = createSaltData({ mailAddress: "test" })
const returnData = createTestEntity(SaltDataTypeRef, { mailAddress: "test" })
const literal = { literal: true }
const saltTypeModel = await resolveTypeReference(SaltDataTypeRef)
const sessionKey = [1, 2, 3]
@ -592,7 +587,7 @@ o.spec("ServiceExecutor", function () {
return: null,
},
}
const giftCardCreateData = createGiftCardCreateData({ message: "test" })
const giftCardCreateData = createTestEntity(GiftCardCreateDataTypeRef, { message: "test" })
const dataTypeModel = await resolveTypeReference(GiftCardCreateDataTypeRef)
const sessionKey = [1, 2, 3]
const encrypted = { encrypted: true }
@ -620,7 +615,7 @@ o.spec("ServiceExecutor", function () {
return: null,
},
}
const giftCardCreateData = createGiftCardCreateData({ message: "test" })
const giftCardCreateData = createTestEntity(GiftCardCreateDataTypeRef, { message: "test" })
await o(() => executor.get(getService, giftCardCreateData)).asyncThrows(ProgrammingError)
verify(restClient.request(anything(), anything()), { ignoreExtraArgs: true, times: 0 })

View file

@ -765,11 +765,11 @@ o.spec("Indexer test", () => {
},
]
let loadedBatches = [
createEntityEventBatch({
createTestEntity(EntityEventBatchTypeRef, {
_id: ["group-mail", loadedNewBatchId],
events: [createTestEntity(EntityUpdateTypeRef), createTestEntity(EntityUpdateTypeRef)],
}),
createEntityEventBatch({
createTestEntity(EntityEventBatchTypeRef, {
_id: ["group-mail", oldestBatchId],
}),
]
@ -798,7 +798,7 @@ o.spec("Indexer test", () => {
const loadPromise = indexer._loadNewEntities(groupIdToEventBatches)
const realtimeUpdates = [
createEntityUpdate({
createTestEntity(EntityUpdateTypeRef, {
instanceId: "realtime",
}),
]
@ -1148,7 +1148,7 @@ o.spec("Indexer test", () => {
})
})
const events1 = [
createEntityUpdate({
createTestEntity(EntityUpdateTypeRef, {
application: MailTypeRef.app,
type: MailTypeRef.type,
operation: OperationType.CREATE,
@ -1162,7 +1162,7 @@ o.spec("Indexer test", () => {
batchId: "batch-id-1",
}
const events2 = [
createEntityUpdate({
createTestEntity(EntityUpdateTypeRef, {
application: MailTypeRef.app,
type: MailTypeRef.type,
operation: OperationType.CREATE,

View file

@ -38,6 +38,8 @@ import {
MailBoxTypeRef,
MailFolderRefTypeRef,
MailboxGroupRootTypeRef,
MailDetailsBlobTypeRef,
MailDetailsTypeRef,
} from "../../../../../src/api/entities/tutanota/TypeRefs.js"
import { mock, spy } from "@tutao/tutanota-test-utils"
import { browserDataStub, createTestEntity, makeCore } from "../../../TestUtils.js"
@ -92,7 +94,10 @@ o.spec("MailIndexer test", () => {
o("createMailIndexEntries without entries", function () {
let mail = createTestEntity(MailTypeRef)
mail.mailDetails = ["details-list-id", "details-id"]
let details = MailWrapper.details(mail, createMailDetails({ body: createTestEntity(BodyTypeRef), recipients: createTestEntity(RecipientsTypeRef) }))
let details = MailWrapper.details(
mail,
createTestEntity(MailDetailsTypeRef, { body: createTestEntity(BodyTypeRef), recipients: createTestEntity(RecipientsTypeRef) }),
)
let files = [createTestEntity(FileTypeRef)]
let indexer = new MailIndexer(
new IndexerCore(dbMock, null as any, browserDataStub),
@ -110,7 +115,10 @@ o.spec("MailIndexer test", () => {
let mail = createTestEntity(MailTypeRef)
mail.subject = "Hello"
mail.mailDetails = ["details-list-id", "details-id"]
let details = MailWrapper.details(mail, createMailDetails({ body: createTestEntity(BodyTypeRef), recipients: createTestEntity(RecipientsTypeRef) }))
let details = MailWrapper.details(
mail,
createTestEntity(MailDetailsTypeRef, { body: createTestEntity(BodyTypeRef), recipients: createTestEntity(RecipientsTypeRef) }),
)
let files = [createTestEntity(FileTypeRef)]
let indexer = new MailIndexer(
new IndexerCore(dbMock, null as any, browserDataStub),
@ -163,7 +171,7 @@ o.spec("MailIndexer test", () => {
mail.sender = sender
mail.mailDetails = ["details-list-id", "details-id"]
let details = MailWrapper.details(mail, createMailDetails({ body: createTestEntity(BodyTypeRef), recipients }))
let details = MailWrapper.details(mail, createTestEntity(MailDetailsTypeRef, { body: createTestEntity(BodyTypeRef), recipients }))
details.getDetails().body.text = "BT"
let files = [createTestEntity(FileTypeRef)]
files[0].mimeType = "binary" // not indexed
@ -925,15 +933,15 @@ function createMailInstances(
mailDetailsBlob: MailDetailsBlob
files: Array<TutanotaFile>
} {
let mail = createMail({
let mail = createTestEntity(MailTypeRef, {
_id: mailId,
_ownerEncSessionKey: new Uint8Array(),
mailDetails: mailDetailsBlobId,
attachments: attachmentIds,
})
let mailDetailsBlob = createMailDetailsBlob({
let mailDetailsBlob = createTestEntity(MailDetailsBlobTypeRef, {
_id: mailDetailsBlobId,
details: createMailDetails({
details: createTestEntity(MailDetailsTypeRef, {
body: createTestEntity(BodyTypeRef),
recipients: createTestEntity(RecipientsTypeRef),
}),

View file

@ -1,10 +1,10 @@
import { AlarmScheduler, AlarmSchedulerImpl } from "../../../src/calendar/date/AlarmScheduler.js"
import o from "@tutao/otest"
import { DateTime } from "luxon"
import { createAlarmInfo, createDateWrapper, createRepeatRule } from "../../../src/api/entities/sys/TypeRefs.js"
import { AlarmInfoTypeRef, DateWrapperTypeRef, RepeatRuleTypeRef } from "../../../src/api/entities/sys/TypeRefs.js"
import { EndType, RepeatPeriod } from "../../../src/api/common/TutanotaConstants.js"
import { DateProvider } from "../../../src/api/common/DateProvider.js"
import { SchedulerMock } from "../TestUtils.js"
import { createTestEntity, SchedulerMock } from "../TestUtils.js"
import { spy } from "@tutao/tutanota-test-utils"
o.spec("AlarmScheduler", function () {
@ -27,7 +27,7 @@ o.spec("AlarmScheduler", function () {
endTime: DateTime.fromISO("2021-04-21T20:30Z").toJSDate(),
summary: "summary",
}
const alarmInfo = createAlarmInfo({
const alarmInfo = createTestEntity(AlarmInfoTypeRef, {
trigger: "10M",
})
const notificationSender = spy()
@ -48,10 +48,10 @@ o.spec("AlarmScheduler", function () {
endTime: DateTime.fromISO("2021-04-21T20:30Z").toJSDate(),
summary: "summary",
}
const alarmInfo = createAlarmInfo({
const alarmInfo = createTestEntity(AlarmInfoTypeRef, {
trigger: "30M",
})
const repeatRule = createRepeatRule({
const repeatRule = createTestEntity(RepeatRuleTypeRef, {
frequency: RepeatPeriod.DAILY,
interval: "1",
endType: EndType.Count,
@ -83,16 +83,16 @@ o.spec("AlarmScheduler", function () {
endTime: DateTime.fromISO("2021-04-21T20:30Z").toJSDate(),
summary: "summary",
}
const alarmInfo = createAlarmInfo({
const alarmInfo = createTestEntity(AlarmInfoTypeRef, {
trigger: "30M",
})
const repeatRule = createRepeatRule({
const repeatRule = createTestEntity(RepeatRuleTypeRef, {
frequency: RepeatPeriod.DAILY,
interval: "1",
endType: EndType.Count,
endValue: "3",
timeZone: "Europe/Berlin",
excludedDates: [createDateWrapper({ date: DateTime.fromISO("2021-04-22T20:00Z").toJSDate() })],
excludedDates: [createTestEntity(DateWrapperTypeRef, { date: DateTime.fromISO("2021-04-22T20:00Z").toJSDate() })],
})
const notificationSender = spy()
alarmScheduler.scheduleAlarm(eventInfo, alarmInfo, repeatRule, notificationSender)
@ -121,7 +121,7 @@ o.spec("AlarmScheduler", function () {
endTime: DateTime.fromISO("2021-04-21T20:30Z").toJSDate(),
summary: "summary",
}
const alarmInfo = createAlarmInfo({
const alarmInfo = createTestEntity(AlarmInfoTypeRef, {
trigger: "10M",
alarmIdentifier: "identifier",
})
@ -143,10 +143,10 @@ o.spec("AlarmScheduler", function () {
endTime: DateTime.fromISO("2021-04-21T20:30Z").toJSDate(),
summary: "summary",
}
const alarmInfo = createAlarmInfo({
const alarmInfo = createTestEntity(AlarmInfoTypeRef, {
trigger: "30M",
})
const repeatRule = createRepeatRule({
const repeatRule = createTestEntity(RepeatRuleTypeRef, {
frequency: RepeatPeriod.DAILY,
interval: "1",
endType: EndType.Count,

View file

@ -9,13 +9,13 @@ import {
} from "../../../src/calendar/export/CalendarImporter.js"
import {
CalendarEvent,
CalendarEventAttendeeTypeRef,
CalendarEventTypeRef,
CalendarGroupRootTypeRef,
createCalendarEvent,
createCalendarEventAttendee,
createEncryptedMailAddress,
EncryptedMailAddressTypeRef,
} from "../../../src/api/entities/tutanota/TypeRefs.js"
import { DateTime } from "luxon"
import { createAlarmInfo, createDateWrapper, createRepeatRule, createUserAlarmInfo, RepeatRuleTypeRef } from "../../../src/api/entities/sys/TypeRefs.js"
import { AlarmInfoTypeRef, DateWrapperTypeRef, RepeatRuleTypeRef, UserAlarmInfoTypeRef } from "../../../src/api/entities/sys/TypeRefs.js"
import { CalendarAttendeeStatus, EndType, RepeatPeriod } from "../../../src/api/common/TutanotaConstants.js"
import { getAllDayDateUTC } from "../../../src/api/common/utils/CommonCalendarUtils.js"
import { getAllDayDateUTCFromZone } from "../../../src/calendar/date/CalendarUtils.js"
@ -23,7 +23,6 @@ import { EventImportRejectionReason, sortOutParsedEvents } from "../../../src/ca
import { getDateInZone } from "./CalendarTestUtils.js"
import { Require } from "@tutao/tutanota-utils"
import { createTestEntity } from "../TestUtils.js"
import { writeFile, writeFileSync } from "fs-extra"
const zone = "Europe/Berlin"
const now = new Date("2019-08-13T14:01:00.630Z")
@ -58,7 +57,7 @@ o.spec("CalendarImporterTest", function () {
o("simple one", function () {
o(
serializeEvent(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n",
@ -107,7 +106,7 @@ o.spec("CalendarImporterTest", function () {
const zone = "utc"
o(
serializeEvent(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n",
@ -151,7 +150,7 @@ o.spec("CalendarImporterTest", function () {
const zone = "America/New_York"
o(
serializeEvent(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "s",
@ -188,21 +187,21 @@ o.spec("CalendarImporterTest", function () {
])
})
o("with alarms", function () {
const alarmOne = createUserAlarmInfo({
alarmInfo: createAlarmInfo({
const alarmOne = createTestEntity(UserAlarmInfoTypeRef, {
alarmInfo: createTestEntity(AlarmInfoTypeRef, {
alarmIdentifier: "123",
trigger: "1D",
}),
})
const alarmTwo = createUserAlarmInfo({
alarmInfo: createAlarmInfo({
const alarmTwo = createTestEntity(UserAlarmInfoTypeRef, {
alarmInfo: createTestEntity(AlarmInfoTypeRef, {
alarmIdentifier: "102",
trigger: "30M",
}),
})
o(
serializeEvent(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n",
@ -258,7 +257,7 @@ o.spec("CalendarImporterTest", function () {
o("with repeat rule (never ends)", function () {
o(
serializeEvent(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n",
@ -282,7 +281,7 @@ o.spec("CalendarImporterTest", function () {
},
{ zone },
).toJSDate(),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
endType: EndType.Never,
interval: "3",
frequency: RepeatPeriod.WEEKLY,
@ -309,7 +308,7 @@ o.spec("CalendarImporterTest", function () {
o("with repeat rule (ends after occurrences)", function () {
o(
serializeEvent(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n",
@ -333,7 +332,7 @@ o.spec("CalendarImporterTest", function () {
},
{ zone },
).toJSDate(),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
endType: EndType.Count,
interval: "3",
frequency: RepeatPeriod.DAILY,
@ -360,7 +359,7 @@ o.spec("CalendarImporterTest", function () {
o("with repeat rule (ends on a date)", function () {
o(
serializeEvent(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n",
@ -384,7 +383,7 @@ o.spec("CalendarImporterTest", function () {
},
{ zone },
).toJSDate(),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
endType: EndType.UntilDate,
interval: "3",
frequency: RepeatPeriod.MONTHLY,
@ -420,7 +419,7 @@ o.spec("CalendarImporterTest", function () {
o("with repeat rule (ends on a date, all-day)", function () {
o(
serializeEvent(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n",
@ -438,7 +437,7 @@ o.spec("CalendarImporterTest", function () {
day: 15,
}).toJSDate(),
),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
endType: EndType.UntilDate,
interval: "3",
frequency: RepeatPeriod.MONTHLY,
@ -498,7 +497,7 @@ o.spec("CalendarImporterTest", function () {
method: "PUBLISH",
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
summary: "Word \\ ; \n",
startTime: DateTime.fromObject(
{
@ -522,7 +521,7 @@ o.spec("CalendarImporterTest", function () {
).toJSDate(),
uid: "test@tuta.com",
hashedUid: null,
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
endType: EndType.Never,
interval: "3",
frequency: RepeatPeriod.WEEKLY,
@ -561,7 +560,7 @@ o.spec("CalendarImporterTest", function () {
method: "PUBLISH",
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
summary: "s",
startTime: DateTime.fromObject(
{
@ -585,13 +584,13 @@ o.spec("CalendarImporterTest", function () {
).toJSDate(),
uid: "test@tuta.com",
hashedUid: null,
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
name: "",
address: "organizer@tuta.com",
}),
attendees: [
createCalendarEventAttendee({
address: createEncryptedMailAddress({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, {
name: "",
address: "test@example.com",
}),
@ -632,7 +631,7 @@ o.spec("CalendarImporterTest", function () {
method: "PUBLISH",
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
summary: "s",
startTime: DateTime.fromObject(
{
@ -656,13 +655,13 @@ o.spec("CalendarImporterTest", function () {
).toJSDate(),
uid: "test@tuta.com",
hashedUid: null,
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
name: "",
address: "organizer@tuta.com",
}),
attendees: [
createCalendarEventAttendee({
address: createEncryptedMailAddress({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, {
name: "",
address: "test@example.com",
}),
@ -705,7 +704,7 @@ o.spec("CalendarImporterTest", function () {
method: "PUBLISH",
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
summary: "s",
startTime: DateTime.fromObject(
{
@ -729,13 +728,13 @@ o.spec("CalendarImporterTest", function () {
).toJSDate(),
uid: "test@tuta.com",
hashedUid: null,
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
name: "",
address: "organizer@tuta.com",
}),
attendees: [
createCalendarEventAttendee({
address: createEncryptedMailAddress({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, {
name: "",
address: "test@example.com",
}),
@ -775,7 +774,7 @@ o.spec("CalendarImporterTest", function () {
zone,
).contents[0],
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
summary: "Labor Day / May Day",
startTime: getAllDayDateUTCFromZone(
DateTime.fromObject(
@ -810,7 +809,7 @@ o.spec("CalendarImporterTest", function () {
})
o("recurrence id on event without UID will be deleted", async function () {
const expected = {
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-07-04T15:00:00.000Z"),
endTime: new Date("2023-07-04T15:30:00.000Z"),
sequence: "1",
@ -869,7 +868,7 @@ o.spec("CalendarImporterTest", function () {
zone,
).contents[0],
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
summary: "Labor Day / May Day",
startTime: getAllDayDateUTCFromZone(
DateTime.fromObject(
@ -930,7 +929,7 @@ o.spec("CalendarImporterTest", function () {
method: "PUBLISH",
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
summary: "Word \\ ; \n",
startTime: DateTime.fromObject(
{
@ -957,7 +956,7 @@ o.spec("CalendarImporterTest", function () {
repeatRule: null,
}),
alarms: [
createAlarmInfo({
createTestEntity(AlarmInfoTypeRef, {
trigger: "15D",
}),
],
@ -996,7 +995,7 @@ o.spec("CalendarImporterTest", function () {
method: "PUBLISH",
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
summary: "Word \\ ; \n",
startTime: DateTime.fromObject(
{
@ -1023,7 +1022,7 @@ o.spec("CalendarImporterTest", function () {
repeatRule: null,
}),
alarms: [
createAlarmInfo({
createTestEntity(AlarmInfoTypeRef, {
trigger: "66M",
}),
],
@ -1060,7 +1059,7 @@ o.spec("CalendarImporterTest", function () {
method: "PUBLISH",
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
summary: "Word \\ ; \n",
startTime: DateTime.fromObject(
{
@ -1093,19 +1092,19 @@ o.spec("CalendarImporterTest", function () {
)
})
o("roundtrip export -> import", async function () {
const alarmOne = createUserAlarmInfo({
alarmInfo: createAlarmInfo({
const alarmOne = createTestEntity(UserAlarmInfoTypeRef, {
alarmInfo: createTestEntity(AlarmInfoTypeRef, {
trigger: "1D",
}),
})
const alarmTwo = createUserAlarmInfo({
alarmInfo: createAlarmInfo({
const alarmTwo = createTestEntity(UserAlarmInfoTypeRef, {
alarmInfo: createTestEntity(AlarmInfoTypeRef, {
trigger: "30M",
}),
})
const events = [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
summary: "Word \\ ; \n simple",
startTime: DateTime.fromObject(
@ -1136,7 +1135,7 @@ o.spec("CalendarImporterTest", function () {
alarms: [],
},
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n alarms",
@ -1167,7 +1166,7 @@ o.spec("CalendarImporterTest", function () {
alarms: [alarmOne, alarmTwo],
},
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n",
@ -1193,7 +1192,7 @@ o.spec("CalendarImporterTest", function () {
).toJSDate(),
uid: "test@tuta.com",
hashedUid: null,
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
endType: EndType.UntilDate,
interval: "3",
frequency: RepeatPeriod.MONTHLY,
@ -1213,7 +1212,7 @@ o.spec("CalendarImporterTest", function () {
alarms: [],
},
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
_id: ["123", "456"],
_ownerGroup: "ownerId",
summary: "Word \\ ; \n",
@ -1233,7 +1232,7 @@ o.spec("CalendarImporterTest", function () {
),
uid: "b64lookingValue==",
hashedUid: null,
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
endType: EndType.UntilDate,
interval: "3",
frequency: RepeatPeriod.MONTHLY,
@ -1339,7 +1338,7 @@ END:VCALENDAR`
_id: ["123", "456"],
}),
alarms: alarms.map((alarmInfo) =>
createUserAlarmInfo({
createTestEntity(UserAlarmInfoTypeRef, {
alarmInfo,
}),
),
@ -1353,8 +1352,14 @@ END:VCALENDAR`
})
o.spec("sortOutParsedEvents", function () {
o("repeated progenitors are skipped", function () {
const progenitor1 = createCalendarEvent({ uid: "hello", startTime: getDateInZone("2023-01-02T13:00") }) as Require<"uid", CalendarEvent>
const progenitor2 = createCalendarEvent({ uid: "hello", startTime: getDateInZone("2023-01-01T13:00") }) as Require<"uid", CalendarEvent>
const progenitor1 = createTestEntity(CalendarEventTypeRef, { uid: "hello", startTime: getDateInZone("2023-01-02T13:00") }) as Require<
"uid",
CalendarEvent
>
const progenitor2 = createTestEntity(CalendarEventTypeRef, { uid: "hello", startTime: getDateInZone("2023-01-01T13:00") }) as Require<
"uid",
CalendarEvent
>
const { rejectedEvents, eventsForCreation } = sortOutParsedEvents(
[
{ event: progenitor1, alarms: [] },
@ -1371,12 +1376,12 @@ END:VCALENDAR`
o(rejectedEvents.get(EventImportRejectionReason.Duplicate)?.[0]).equals(progenitor2)
})
o("imported altered instances are added as exclusions", function () {
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
uid: "hello",
startTime: getDateInZone("2023-01-02T13:00"),
repeatRule: createTestEntity(RepeatRuleTypeRef),
}) as Require<"uid", CalendarEvent>
const altered = createCalendarEvent({
const altered = createTestEntity(CalendarEventTypeRef, {
uid: "hello",
startTime: getDateInZone("2023-01-02T14:00"),
recurrenceId: getDateInZone("2023-01-02T13:00"),
@ -1397,7 +1402,7 @@ END:VCALENDAR`
o.spec("serializeRepeatRule", function () {
o("when RRULE is UNTIL and not all date the timestamp of the end of last day is written", function () {
const repeatRule = createRepeatRule({
const repeatRule = createTestEntity(RepeatRuleTypeRef, {
endType: EndType.UntilDate,
endValue: String(DateTime.fromObject({ year: 2019, month: 9, day: 20 }, { zone: "UTC" }).toMillis()),
frequency: RepeatPeriod.MONTHLY,
@ -1413,7 +1418,7 @@ END:VCALENDAR`
})
o("one excluded date", function () {
o(serializeExcludedDates([createDateWrapper({ date: new Date("2023-01-14T22:00:00Z") })], "Europe/Berlin")).deepEquals([
o(serializeExcludedDates([createTestEntity(DateWrapperTypeRef, { date: new Date("2023-01-14T22:00:00Z") })], "Europe/Berlin")).deepEquals([
"EXDATE;TZID=Europe/Berlin:20230114T230000",
])
})
@ -1421,7 +1426,10 @@ END:VCALENDAR`
o("more than one excluded date", function () {
o(
serializeExcludedDates(
[createDateWrapper({ date: new Date("2023-01-14T22:00:00Z") }), createDateWrapper({ date: new Date("2023-01-21T22:00:00Z") })],
[
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-01-14T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-01-21T22:00:00Z") }),
],
"Europe/Berlin",
),
).deepEquals(["EXDATE;TZID=Europe/Berlin:20230114T230000,20230121T230000"])

View file

@ -1,14 +1,11 @@
import o from "@tutao/otest"
import type { CalendarEvent, CalendarGroupRoot } from "../../../src/api/entities/tutanota/TypeRefs.js"
import {
CalendarEventAttendeeTypeRef,
CalendarEventTypeRef,
CalendarEventUpdateTypeRef,
createCalendarEvent,
createCalendarEventAttendee,
createCalendarEventUpdate,
createCalendarGroupRoot,
createEncryptedMailAddress,
createFile,
CalendarGroupRootTypeRef,
EncryptedMailAddressTypeRef,
FileTypeRef,
} from "../../../src/api/entities/tutanota/TypeRefs.js"
import { incrementByRepeatPeriod } from "../../../src/calendar/date/CalendarUtils.js"
@ -19,7 +16,7 @@ import { DateTime } from "luxon"
import type { EntityUpdateData } from "../../../src/api/main/EventController.js"
import { EntityEventsListener, EventController } from "../../../src/api/main/EventController.js"
import { Notifications } from "../../../src/gui/Notifications.js"
import { AlarmInfo, createAlarmInfo, createUser, createUserAlarmInfo, createUserAlarmInfoListType } from "../../../src/api/entities/sys/TypeRefs.js"
import { AlarmInfo, AlarmInfoTypeRef, UserAlarmInfoListTypeTypeRef, UserAlarmInfoTypeRef, UserTypeRef } from "../../../src/api/entities/sys/TypeRefs.js"
import { EntityRestClientMock } from "../api/worker/rest/EntityRestClientMock.js"
import type { UserController } from "../../../src/api/main/UserController.js"
import { NotFoundError } from "../../../src/api/common/error/RestError.js"
@ -36,6 +33,7 @@ import { func, matchers, when } from "testdouble"
import { elementIdPart, getElementId, listIdPart } from "../../../src/api/common/utils/EntityUtils.js"
import { createDataFile } from "../../../src/api/common/DataFile.js"
import { SessionKeyNotFoundError } from "../../../src/api/common/error/SessionKeyNotFoundError.js"
import { createTestEntity } from "../TestUtils.js"
o.spec("CalendarModel", function () {
o.spec("incrementByRepeatPeriod", function () {
@ -189,7 +187,7 @@ o.spec("CalendarModel", function () {
const loginController = makeLoginController()
const alarmsListId = neverNull(loginController.getUserController().user.alarmInfoList).alarms
o.beforeEach(function () {
groupRoot = createCalendarGroupRoot({
groupRoot = createTestEntity(CalendarGroupRootTypeRef, {
_id: "groupRootId",
longEvents: "longEvents",
shortEvents: "shortEvents",
@ -199,7 +197,7 @@ o.spec("CalendarModel", function () {
})
o("reply but sender is not a guest", async function () {
const uid = "uid"
const existingEvent = createCalendarEvent({ uid })
const existingEvent = createTestEntity(CalendarEventTypeRef, { uid })
const calendarFacade = makeCalendarFacade(
{
getEventsByUid: (loadUid) =>
@ -217,7 +215,7 @@ o.spec("CalendarModel", function () {
method: CalendarMethod.REPLY,
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
uid,
}) as CalendarEventProgenitor,
alarms: [],
@ -230,23 +228,23 @@ o.spec("CalendarModel", function () {
const uid = "uid"
const sender = "sender@example.com"
const anotherGuest = "another-attendee"
const alarm = createAlarmInfo({
const alarm = createTestEntity(AlarmInfoTypeRef, {
_id: "alarm-id",
})
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_id: ["listId", "eventId"],
uid,
_ownerGroup: groupRoot._id,
summary: "v1",
attendees: [
createCalendarEventAttendee({
address: createEncryptedMailAddress({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
status: CalendarAttendeeStatus.NEEDS_ACTION,
}),
createCalendarEventAttendee({
address: createEncryptedMailAddress({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, {
address: anotherGuest,
}),
status: CalendarAttendeeStatus.NEEDS_ACTION,
@ -255,7 +253,7 @@ o.spec("CalendarModel", function () {
alarmInfos: [[alarmsListId, alarm._id]],
})
restClientMock.addListInstances(
createUserAlarmInfo({
createTestEntity(UserAlarmInfoTypeRef, {
_id: [alarmsListId, alarm._id],
alarmInfo: alarm,
}),
@ -278,18 +276,18 @@ o.spec("CalendarModel", function () {
method: CalendarMethod.REPLY,
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
uid,
attendees: [
createCalendarEventAttendee({
address: createEncryptedMailAddress({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
status: CalendarAttendeeStatus.ACCEPTED,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
// should be ignored
address: createEncryptedMailAddress({
address: createTestEntity(EncryptedMailAddressTypeRef, {
address: anotherGuest,
}),
status: CalendarAttendeeStatus.DECLINED,
@ -308,14 +306,14 @@ o.spec("CalendarModel", function () {
o(createdEvent.uid).equals(existingEvent.uid)
o(createdEvent.summary).equals(existingEvent.summary)
o(createdEvent.attendees).deepEquals([
createCalendarEventAttendee({
address: createEncryptedMailAddress({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
status: CalendarAttendeeStatus.ACCEPTED,
}),
createCalendarEventAttendee({
address: createEncryptedMailAddress({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, {
address: "another-attendee",
}),
status: CalendarAttendeeStatus.NEEDS_ACTION,
@ -343,11 +341,11 @@ o.spec("CalendarModel", function () {
method: CalendarMethod.REQUEST,
contents: [
{
event: createCalendarEvent({
event: createTestEntity(CalendarEventTypeRef, {
uid,
attendees: [
createCalendarEventAttendee({
address: createEncryptedMailAddress({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
status: CalendarAttendeeStatus.ACCEPTED,
@ -363,23 +361,23 @@ o.spec("CalendarModel", function () {
o("request as an update", async function () {
const uid = "uid"
const sender = "sender@example.com"
const alarm = createAlarmInfo({
const alarm = createTestEntity(AlarmInfoTypeRef, {
_id: "alarm-id",
})
restClientMock.addListInstances(
createUserAlarmInfo({
createTestEntity(UserAlarmInfoTypeRef, {
_id: [alarmsListId, alarm._id],
alarmInfo: alarm,
}),
)
const startTime = new Date()
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_id: ["listId", "eventId"],
_ownerGroup: groupRoot._id,
summary: "v1",
sequence: "1",
uid,
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
alarmInfos: [[alarmsListId, alarm._id]],
@ -398,11 +396,11 @@ o.spec("CalendarModel", function () {
restClientMock,
calendarFacade,
})
const sentEvent = createCalendarEvent({
const sentEvent = createTestEntity(CalendarEventTypeRef, {
summary: "v2",
uid,
sequence: "2",
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
startTime,
@ -431,22 +429,22 @@ o.spec("CalendarModel", function () {
o("event is re-created when the start time changes", async function () {
const uid = "uid"
const sender = "sender@example.com"
const alarm = createAlarmInfo({
const alarm = createTestEntity(AlarmInfoTypeRef, {
_id: "alarm-id",
})
restClientMock.addListInstances(
createUserAlarmInfo({
createTestEntity(UserAlarmInfoTypeRef, {
_id: [alarmsListId, alarm._id],
alarmInfo: alarm,
}),
)
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_id: ["listId", "eventId"],
_ownerGroup: groupRoot._id,
summary: "v1",
sequence: "1",
uid,
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
startTime: DateTime.fromObject(
@ -472,7 +470,7 @@ o.spec("CalendarModel", function () {
restClientMock,
calendarFacade,
})
const sentEvent = createCalendarEvent({
const sentEvent = createTestEntity(CalendarEventTypeRef, {
summary: "v2",
uid,
sequence: "2",
@ -484,7 +482,7 @@ o.spec("CalendarModel", function () {
},
{ zone: "UTC" },
).toJSDate(),
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
})
@ -518,12 +516,12 @@ o.spec("CalendarModel", function () {
o("event is cancelled by organizer", async function () {
const uid = "uid"
const sender = "sender@example.com"
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_id: ["listId", "eventId"],
_ownerGroup: groupRoot._id,
sequence: "1",
uid,
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
})
@ -541,10 +539,10 @@ o.spec("CalendarModel", function () {
restClientMock,
calendarFacade: calendarFacade,
})
const sentEvent = createCalendarEvent({
const sentEvent = createTestEntity(CalendarEventTypeRef, {
uid,
sequence: "2",
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
})
@ -562,12 +560,12 @@ o.spec("CalendarModel", function () {
o("event is cancelled by someone else than organizer", async function () {
const uid = "uid"
const sender = "sender@example.com"
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_id: ["listId", "eventId"],
_ownerGroup: groupRoot._id,
sequence: "1",
uid,
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
})
@ -577,10 +575,10 @@ o.spec("CalendarModel", function () {
workerClient,
restClientMock,
})
const sentEvent = createCalendarEvent({
const sentEvent = createTestEntity(CalendarEventTypeRef, {
uid,
sequence: "2",
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
})
@ -597,23 +595,23 @@ o.spec("CalendarModel", function () {
})
})
o("reprocess deferred calendar events with no owner enc session key", async function () {
const calendarFile = createFile({
const calendarFile = createTestEntity(FileTypeRef, {
_id: ["fileListId", "fileId"],
})
const eventUpdate = createCalendarEventUpdate({
const eventUpdate = createTestEntity(CalendarEventUpdateTypeRef, {
_id: ["calendarEventUpdateListId", "calendarEventUpdateId"],
file: calendarFile._id,
})
const uid = "uid"
const sender = "sender@example.com"
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_id: ["calendarListId", "eventId"],
_ownerGroup: groupRoot._id,
sequence: "1",
uid,
organizer: createEncryptedMailAddress({
organizer: createTestEntity(EncryptedMailAddressTypeRef, {
address: sender,
}),
})
@ -717,13 +715,14 @@ function makeWorkerClient(): WorkerClient {
}
function makeLoginController(props: Partial<UserController> = {}): LoginController {
const alarmInfoList = createTestEntity(UserAlarmInfoListTypeTypeRef, {
alarms: "alarms",
})
const userController = downcast(
Object.assign(props, {
user: createUser({
user: createTestEntity(UserTypeRef, {
_id: "user-id",
alarmInfoList: createUserAlarmInfoListType({
alarms: "alarms",
}),
alarmInfoList,
}),
}),
)

View file

@ -14,9 +14,10 @@ import {
} from "../../../src/calendar/export/CalendarParser.js"
import { ParserError, StringIterator } from "../../../src/misc/parsing/ParserCombinator.js"
import { DateTime } from "luxon"
import { createDateWrapper } from "../../../src/api/entities/sys/TypeRefs.js"
import { DateWrapperTypeRef } from "../../../src/api/entities/sys/TypeRefs.js"
import { getDateInUTC, zone } from "./CalendarTestUtils.js"
import { AlarmIntervalUnit } from "../../../src/calendar/date/CalendarUtils.js"
import { createTestEntity } from "../TestUtils.js"
o.spec("CalendarParser", function () {
o.spec("propertySequenceParser", function () {
@ -223,15 +224,15 @@ o.spec("CalendarParser", function () {
o("are excluded dates deduplicated", function () {
const parsedDates = parseExDates([{ name: "EXDATES", params: {}, value: "20230308T230000Z,20230308T230000Z,20230309T230000Z" }])
o(parsedDates).deepEquals([
createDateWrapper({ date: new Date("2023-03-08T23:00:00Z") }),
createDateWrapper({ date: new Date("2023-03-09T23:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-08T23:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-09T23:00:00Z") }),
])
})
o("are excluded dates sorted", function () {
const parsedDates = parseExDates([{ name: "EXDATES", params: {}, value: "20230313T230000Z,20230309T230000Z" }])
o(parsedDates).deepEquals([
createDateWrapper({ date: new Date("2023-03-09T23:00:00Z") }),
createDateWrapper({ date: new Date("2023-03-13T23:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-09T23:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-13T23:00:00Z") }),
])
})
o("multiple exdates in separate lines are parsed", function () {
@ -244,8 +245,8 @@ o.spec("CalendarParser", function () {
},
])
o(parsedDates).deepEquals([
createDateWrapper({ date: new Date("2023-02-03T23:00:00Z") }),
createDateWrapper({ date: new Date("2023-03-09T23:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-02-03T23:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-09T23:00:00Z") }),
])
})
o("deduplication over multiple lines works", function () {
@ -258,16 +259,16 @@ o.spec("CalendarParser", function () {
},
])
o(parsedDates).deepEquals([
createDateWrapper({ date: new Date("2023-01-14T23:00:00Z") }),
createDateWrapper({ date: new Date("2023-03-02T23:00:00Z") }),
createDateWrapper({ date: new Date("2023-03-09T23:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-01-14T23:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-02T23:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-09T23:00:00Z") }),
])
})
o("is timezone parsed", function () {
const parsedDates = parseExDates([{ name: "EXDATES", params: { TZID: "Europe/Berlin" }, value: "20230309T230000,20230302T230000" }])
o(parsedDates).deepEquals([
createDateWrapper({ date: new Date("2023-03-02T22:00:00Z") }),
createDateWrapper({ date: new Date("2023-03-09T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-02T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-09T22:00:00Z") }),
])
})
o(" deduplication over different timezones", function () {
@ -275,7 +276,7 @@ o.spec("CalendarParser", function () {
{ name: "EXDATES", params: { TZID: "Europe/Berlin" }, value: "20230309T230000" },
{ name: "EXDATES", params: { TZID: "Europe/Sofia" }, value: "20230310T000000" },
])
o(parsedDates).deepEquals([createDateWrapper({ date: new Date("2023-03-09T22:00:00Z") })])
o(parsedDates).deepEquals([createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-09T22:00:00Z") })])
})
})

View file

@ -1,6 +1,7 @@
import { AccountType, ContactAddressType, FeatureType, GroupType, ShareCapability, TimeFormat } from "../../../src/api/common/TutanotaConstants.js"
import type { UserController } from "../../../src/api/main/UserController.js"
import {
BookingsRefTypeRef,
createBookingsRef,
createCustomer,
createCustomerInfo,
@ -11,14 +12,26 @@ import {
createMailAddressAlias,
createPlanConfiguration,
createUser,
CustomerInfoTypeRef,
CustomerTypeRef,
Feature,
FeatureTypeRef,
GroupInfoTypeRef,
GroupMembershipTypeRef,
GroupTypeRef,
MailAddressAliasTypeRef,
PlanConfigurationTypeRef,
User,
UserTypeRef,
} from "../../../src/api/entities/sys/TypeRefs.js"
import { GENERATED_MAX_ID } from "../../../src/api/common/utils/EntityUtils.js"
import { downcast, LazyLoaded } from "@tutao/tutanota-utils"
import type { CalendarEvent } from "../../../src/api/entities/tutanota/TypeRefs.js"
import {
CalendarEventTypeRef,
CalendarGroupRootTypeRef,
ContactAddressTypeRef,
ContactTypeRef,
createCalendarEvent,
createCalendarGroupRoot,
createContact,
@ -28,8 +41,10 @@ import {
createMailboxGroupRoot,
createTutanotaProperties,
EncryptedMailAddress,
EncryptedMailAddressTypeRef,
MailboxGroupRootTypeRef,
MailBoxTypeRef,
TutanotaPropertiesTypeRef,
} from "../../../src/api/entities/tutanota/TypeRefs.js"
import type { MailboxDetail } from "../../../src/mail/model/MailModel.js"
import o from "@tutao/otest"
@ -45,7 +60,7 @@ export const ownerMailAddress = "calendarowner@tutanota.de" as const
export const ownerId = "ownerId" as const
export const calendarGroupId = "0" as const
export const ownerAddress = createEncryptedMailAddress({
export const ownerAddress = createTestEntity(EncryptedMailAddressTypeRef, {
address: ownerMailAddress,
name: "Calendar Owner",
})
@ -55,7 +70,7 @@ export const ownerRecipient: Recipient = {
type: RecipientType.INTERNAL,
contact: null,
}
export const ownerAlias = createEncryptedMailAddress({
export const ownerAlias = createTestEntity(EncryptedMailAddressTypeRef, {
address: "calendarowneralias@tutanota.de",
name: "Calendar Owner Alias",
})
@ -65,7 +80,7 @@ export const ownerAliasRecipient: Recipient = {
type: RecipientType.INTERNAL,
contact: null,
}
export const otherAddress = createEncryptedMailAddress({
export const otherAddress = createTestEntity(EncryptedMailAddressTypeRef, {
address: "someone@tutanota.de",
name: "Some One",
})
@ -73,18 +88,18 @@ export const otherRecipient: Recipient = {
address: otherAddress.address,
name: otherAddress.name,
type: RecipientType.EXTERNAL,
contact: createContact({
contact: createTestEntity(ContactTypeRef, {
nickname: otherAddress.name,
presharedPassword: "otherPassword",
addresses: [
createContactAddress({
createTestEntity(ContactAddressTypeRef, {
address: otherAddress.address,
type: ContactAddressType.WORK,
}),
],
}),
}
export const otherAddress2 = createEncryptedMailAddress({
export const otherAddress2 = createTestEntity(EncryptedMailAddressTypeRef, {
address: "someoneelse@tutanota.de",
name: "Some One Else",
})
@ -92,11 +107,11 @@ export const otherRecipient2: Recipient = {
address: otherAddress2.address,
name: otherAddress2.name,
type: RecipientType.INTERNAL,
contact: createContact({
contact: createTestEntity(ContactTypeRef, {
nickname: otherAddress2.name,
presharedPassword: "otherPassword2",
addresses: [
createContactAddress({
createTestEntity(ContactAddressTypeRef, {
address: otherAddress2.address,
type: ContactAddressType.WORK,
}),
@ -104,16 +119,16 @@ export const otherRecipient2: Recipient = {
}),
}
export const thirdAddress = createEncryptedMailAddress({ address: "somethirdaddress@tuta.com", name: "thirdperson" })
export const thirdAddress = createTestEntity(EncryptedMailAddressTypeRef, { address: "somethirdaddress@tuta.com", name: "thirdperson" })
export const thirdRecipient: Recipient = {
address: thirdAddress.address,
name: thirdAddress.name,
type: RecipientType.INTERNAL,
contact: createContact({
contact: createTestEntity(ContactTypeRef, {
nickname: "drei",
presharedPassword: "noPassword",
addresses: [
createContactAddress({
createTestEntity(ContactAddressTypeRef, {
address: thirdAddress.address,
type: ContactAddressType.OTHER,
}),
@ -125,11 +140,11 @@ export const calendars: ReadonlyMap<Id, CalendarInfo> = new Map([
[
"ownCalendar",
{
groupRoot: createCalendarGroupRoot({}),
groupRoot: createTestEntity(CalendarGroupRootTypeRef, {}),
shared: false,
longEvents: new LazyLoaded(() => Promise.resolve([])),
groupInfo: createGroupInfo({}),
group: createGroup({
groupInfo: createTestEntity(GroupInfoTypeRef, {}),
group: createTestEntity(GroupTypeRef, {
_id: "ownCalendar",
user: "ownerId",
type: GroupType.Calendar,
@ -139,11 +154,11 @@ export const calendars: ReadonlyMap<Id, CalendarInfo> = new Map([
[
"sharedCalendar",
{
groupRoot: createCalendarGroupRoot({}),
groupRoot: createTestEntity(CalendarGroupRootTypeRef, {}),
shared: true,
longEvents: new LazyLoaded(() => Promise.resolve([])),
groupInfo: createGroupInfo({}),
group: createGroup({
groupInfo: createTestEntity(GroupInfoTypeRef, {}),
group: createTestEntity(GroupTypeRef, {
_id: "sharedCalendar",
user: "otherId",
type: GroupType.Calendar,
@ -161,38 +176,38 @@ export function makeUserController(
businessFeatureOrdered: boolean = false,
isNewPaidPlan: boolean = false,
): UserController {
const bookingsRef = createBookingsRef({
const bookingsRef = createTestEntity(BookingsRefTypeRef, {
items: GENERATED_MAX_ID,
})
const customizations: Feature[] = []
if (businessFeatureOrdered) {
customizations.push(
createFeature({
createTestEntity(FeatureTypeRef, {
feature: FeatureType.BusinessFeatureEnabled,
}),
)
}
return downcast({
user: createUser({
user: createTestEntity(UserTypeRef, {
_id: ownerId,
memberships: [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
groupType: GroupType.Mail,
}),
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
groupType: GroupType.Contact,
}),
],
accountType,
}),
props: createTutanotaProperties({
props: createTestEntity(TutanotaPropertiesTypeRef, {
defaultSender: defaultSender || ownerMailAddress,
}),
userGroupInfo: createGroupInfo({
userGroupInfo: createTestEntity(GroupInfoTypeRef, {
mailAddressAliases: aliases.map((address) =>
createMailAddressAlias({
createTestEntity(MailAddressAliasTypeRef, {
mailAddress: address,
enabled: true,
}),
@ -207,13 +222,13 @@ export function makeUserController(
isNewPaidPlan: () => isNewPaidPlan,
loadCustomer: () =>
Promise.resolve(
createCustomer({
createTestEntity(CustomerTypeRef, {
customizations: customizations,
}),
),
loadCustomerInfo: () =>
Promise.resolve(
createCustomerInfo({
createTestEntity(CustomerInfoTypeRef, {
bookings: bookingsRef,
}),
),
@ -223,7 +238,7 @@ export function makeUserController(
},
getPlanConfig: () =>
Promise.resolve(
createPlanConfiguration({
createTestEntity(PlanConfigurationTypeRef, {
eventInvites: businessFeatureOrdered || isNewPaidPlan,
}),
),
@ -235,7 +250,7 @@ export function makeMailboxDetail(): MailboxDetail {
mailbox: createTestEntity(MailBoxTypeRef),
folders: new FolderSystem([]),
mailGroupInfo: createTestEntity(GroupInfoTypeRef),
mailGroup: createGroup({
mailGroup: createTestEntity(GroupTypeRef, {
user: ownerId,
}),
mailboxGroupRoot: createTestEntity(MailboxGroupRootTypeRef),
@ -250,7 +265,7 @@ export function makeCalendarInfo(type: "own" | "shared", id: string): CalendarIn
}),
longEvents: new LazyLoaded(() => Promise.resolve([])),
groupInfo: downcast({}),
group: createGroup({
group: createTestEntity(GroupTypeRef, {
_id: id,
type: GroupType.Calendar,
user: type === "own" ? ownerId : "anotherUserId",
@ -285,7 +300,7 @@ function id(element: string): IdTuple {
}
export function makeEvent(_id: string, startTime: Date, endTime: Date, uid: string = ""): CalendarEvent {
return createCalendarEvent({
return createTestEntity(CalendarEventTypeRef, {
_ownerGroup: "ownerGroup",
_id: id(_id),
startTime,
@ -296,7 +311,7 @@ export function makeEvent(_id: string, startTime: Date, endTime: Date, uid: stri
export function addCapability(user: User, groupId: Id, capability: ShareCapability) {
user.memberships.push(
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
group: groupId,
capability,
}),

View file

@ -29,7 +29,7 @@ import {
StandardAlarmInterval,
} from "../../../src/calendar/date/CalendarUtils.js"
import { lang } from "../../../src/misc/LanguageViewModel.js"
import { createDateWrapper, createGroup, createGroupMembership, createUser, User } from "../../../src/api/entities/sys/TypeRefs.js"
import { DateWrapperTypeRef, GroupMembershipTypeRef, GroupTypeRef, User, UserTypeRef } from "../../../src/api/entities/sys/TypeRefs.js"
import { AccountType, EndType, GroupType, RepeatPeriod, ShareCapability } from "../../../src/api/common/TutanotaConstants.js"
import { timeStringFromParts } from "../../../src/misc/Formatter.js"
import { DateTime } from "luxon"
@ -37,11 +37,11 @@ import { generateEventElementId, getAllDayDateUTC } from "../../../src/api/commo
import { hasCapabilityOnGroup } from "../../../src/sharing/GroupUtils.js"
import type { CalendarEvent } from "../../../src/api/entities/tutanota/TypeRefs.js"
import {
CalendarEventAttendeeTypeRef,
CalendarEventTypeRef,
createCalendarEvent,
createCalendarEventAttendee,
CalendarRepeatRuleTypeRef,
createCalendarRepeatRule,
createEncryptedMailAddress,
EncryptedMailAddressTypeRef,
} from "../../../src/api/entities/tutanota/TypeRefs.js"
import { clone, getStartOfDay, identity, lastThrow, neverNull } from "@tutao/tutanota-utils"
import { Time } from "../../../src/calendar/date/Time.js"
@ -427,22 +427,23 @@ o.spec("calendar utils tests", function () {
let groupMembership
let groupOwnerMembership
o.before(function () {
group = createGroup({
// @ts-ignore
group = createTestEntity(GroupTypeRef, {
_id: "g1",
type: GroupType.Calendar,
user: "groupOwner",
})
groupMembership = createGroupMembership({
groupMembership = createTestEntity(GroupMembershipTypeRef, {
group: group._id,
})
groupOwnerMembership = createGroupMembership({
groupOwnerMembership = createTestEntity(GroupMembershipTypeRef, {
group: group._id,
})
ownerUser = createUser({
ownerUser = createTestEntity(UserTypeRef, {
_id: "groupOwner",
memberships: [groupOwnerMembership],
})
user = createUser({
user = createTestEntity(UserTypeRef, {
_id: "groupMember",
memberships: [groupMembership],
})
@ -679,7 +680,7 @@ o.spec("calendar utils tests", function () {
const zone = getTimeZone()
function eventOn(start: Date, end: Date): CalendarEvent {
return createCalendarEvent({
return createTestEntity(CalendarEventTypeRef, {
startTime: start,
endTime: end,
})
@ -734,7 +735,7 @@ o.spec("calendar utils tests", function () {
o("events with invalid dates are detected", function () {
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("nan"),
endTime: new Date("1990"),
}),
@ -742,7 +743,7 @@ o.spec("calendar utils tests", function () {
).equals(CalendarEventValidity.InvalidContainsInvalidDate)
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("1991"),
endTime: new Date("nan"),
}),
@ -750,7 +751,7 @@ o.spec("calendar utils tests", function () {
).equals(CalendarEventValidity.InvalidContainsInvalidDate)
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("nan"),
endTime: new Date("nan"),
}),
@ -760,7 +761,7 @@ o.spec("calendar utils tests", function () {
o("events with start date not before end date are detected", function () {
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("1990"),
endTime: new Date("1990"),
}),
@ -768,7 +769,7 @@ o.spec("calendar utils tests", function () {
).equals(CalendarEventValidity.InvalidEndBeforeStart)
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("1990"),
endTime: new Date("1980"),
}),
@ -778,7 +779,7 @@ o.spec("calendar utils tests", function () {
o("events with date before 1970 are detected", function () {
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("1969"),
endTime: new Date("1990"),
}),
@ -786,7 +787,7 @@ o.spec("calendar utils tests", function () {
).equals(CalendarEventValidity.InvalidPre1970)
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("1960"),
endTime: new Date("1966"),
}),
@ -794,7 +795,7 @@ o.spec("calendar utils tests", function () {
).equals(CalendarEventValidity.InvalidPre1970)
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("1970"),
endTime: new Date("1966"),
}),
@ -804,7 +805,7 @@ o.spec("calendar utils tests", function () {
o("valid events are detected", function () {
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: getDateInUTC("1970"),
endTime: getDateInUTC("1990"),
}),
@ -812,7 +813,7 @@ o.spec("calendar utils tests", function () {
).equals(CalendarEventValidity.Valid)("events on the cusp of 1970 UTC are valid")
o(
checkEventValidity(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: getDateInZone("1971"),
endTime: getDateInZone("2022"),
}),
@ -934,7 +935,7 @@ o.spec("calendar utils tests", function () {
event.repeatRule.endValue = "2"
addDaysForRecurringEvent(eventsForDays, event, getMonthRange(getDateInZone("2023-07-01"), zone), zone)
o(countDaysWithEvents(eventsForDays)).equals(2)
event.repeatRule.excludedDates = [createDateWrapper({ date: getDateInZone("2023-07-21T12:00") })]
event.repeatRule.excludedDates = [createTestEntity(DateWrapperTypeRef, { date: getDateInZone("2023-07-21T12:00") })]
addDaysForRecurringEvent(eventsForDays, event, getMonthRange(getDateInZone("2023-07-01"), zone), zone)
o(countDaysWithEvents(eventsForDays)).equals(1)
})
@ -1317,7 +1318,7 @@ o.spec("calendar utils tests", function () {
const repeatRule = createRepeatRuleWithValues(RepeatPeriod.DAILY, 1, zone)
repeatRule.endValue = "2"
repeatRule.endType = EndType.Count
repeatRule.excludedDates = [createDateWrapper({ date: event.startTime })]
repeatRule.excludedDates = [createTestEntity(DateWrapperTypeRef, { date: event.startTime })]
event.repeatRule = repeatRule
const alteredEvent = clone(event)
alteredEvent._id = ["shortEvents", generateEventElementId(alteredEvent.startTime.getTime())]
@ -1441,30 +1442,34 @@ o.spec("calendar utils tests", function () {
})
o.spec("calendarEventHasMoreThanOneOccurrencesLeft", function () {
o("event without end condition has more than one occurrence", function () {
const repeatRule = createCalendarRepeatRule({
const repeatRule = createTestEntity(CalendarRepeatRuleTypeRef, {
endType: EndType.Never,
frequency: RepeatPeriod.DAILY,
interval: "1",
})
const progenitor = createCalendarEvent({ startTime: new Date(), endTime: new Date(), repeatRule }) as CalendarEventProgenitor
const progenitor = createTestEntity(CalendarEventTypeRef, { startTime: new Date(), endTime: new Date(), repeatRule }) as CalendarEventProgenitor
o(calendarEventHasMoreThanOneOccurrencesLeft({ progenitor, ownerGroup: "", alteredInstances: [] })).equals(true)
})
o("event without repeat rule has less than two occurrences", function () {
const progenitor = createCalendarEvent({ startTime: new Date(), endTime: new Date(), repeatRule: null }) as CalendarEventProgenitor
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date(),
endTime: new Date(),
repeatRule: null,
}) as CalendarEventProgenitor
o(calendarEventHasMoreThanOneOccurrencesLeft({ progenitor, ownerGroup: "", alteredInstances: [] })).equals(false)
})
o("event with higher count than exclusions+1 has more left", function () {
const repeatRule = createCalendarRepeatRule({
const repeatRule = createTestEntity(CalendarRepeatRuleTypeRef, {
endType: EndType.Count,
frequency: RepeatPeriod.DAILY,
interval: "1",
endValue: "3",
excludedDates: [createDateWrapper({ date: new Date("2023-03-03T22:00:00Z") })],
excludedDates: [createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-03T22:00:00Z") })],
timeZone: zone,
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-02T22:00:00Z"),
endTime: new Date("2023-03-02T23:00:00Z"),
repeatRule,
@ -1473,15 +1478,18 @@ o.spec("calendar utils tests", function () {
})
o("event with count and enough exclusions has less than two left", function () {
const repeatRule = createCalendarRepeatRule({
const repeatRule = createTestEntity(CalendarRepeatRuleTypeRef, {
endType: EndType.Count,
frequency: RepeatPeriod.DAILY,
interval: "1",
endValue: "3",
excludedDates: [createDateWrapper({ date: new Date("2023-03-03T22:00:00Z") }), createDateWrapper({ date: new Date("2023-03-04T22:00:00Z") })],
excludedDates: [
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-03T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-04T22:00:00Z") }),
],
timeZone: zone,
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-02T22:00:00Z"),
endTime: new Date("2023-03-02T23:00:00Z"),
repeatRule,
@ -1490,15 +1498,18 @@ o.spec("calendar utils tests", function () {
})
o("event with count and enough exclusions has less than two left, first is excluded", function () {
const repeatRule = createCalendarRepeatRule({
const repeatRule = createTestEntity(CalendarRepeatRuleTypeRef, {
endType: EndType.Count,
frequency: RepeatPeriod.DAILY,
interval: "1",
endValue: "3",
excludedDates: [createDateWrapper({ date: new Date("2023-03-02T22:00:00Z") }), createDateWrapper({ date: new Date("2023-03-04T22:00:00Z") })],
excludedDates: [
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-02T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-04T22:00:00Z") }),
],
timeZone: zone,
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-02T22:00:00Z"),
endTime: new Date("2023-03-02T23:00:00Z"),
repeatRule,
@ -1522,9 +1533,12 @@ o.spec("calendar utils tests", function () {
).toMillis(),
),
timeZone: zone,
excludedDates: [createDateWrapper({ date: new Date("2023-03-02T22:00:00Z") }), createDateWrapper({ date: new Date("2023-03-04T22:00:00Z") })],
excludedDates: [
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-02T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-04T22:00:00Z") }),
],
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-02T22:00:00Z"),
endTime: new Date("2023-03-02T23:00:00Z"),
repeatRule,
@ -1548,9 +1562,12 @@ o.spec("calendar utils tests", function () {
).toMillis(),
),
timeZone: zone,
excludedDates: [createDateWrapper({ date: new Date("2023-03-02T22:00:00Z") }), createDateWrapper({ date: new Date("2023-03-04T22:00:00Z") })],
excludedDates: [
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-02T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-04T22:00:00Z") }),
],
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-02T22:00:00Z"),
endTime: new Date("2023-03-02T23:00:00Z"),
repeatRule,
@ -1575,15 +1592,15 @@ o.spec("calendar utils tests", function () {
),
timeZone: zone,
excludedDates: [
createDateWrapper({ date: new Date("2023-03-02T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-02T22:00:00Z") }),
// 2023-03-03T22:00:00Z not excluded
createDateWrapper({ date: new Date("2023-03-04T22:00:00Z") }),
createDateWrapper({ date: new Date("2023-03-05T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-04T22:00:00Z") }),
createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-05T22:00:00Z") }),
// 2023-03-06T22:00:00Z not excluded
// 2023-03-07T22:00:00Z not excluded
],
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-02T22:00:00Z"),
endTime: new Date("2023-03-02T23:00:00Z"),
repeatRule,
@ -1598,18 +1615,18 @@ o.spec("calendar utils tests", function () {
})
o("event with end date after 2 occurrences and an altered instance is considered to have more than one occurrence", function () {
const repeatRule = createCalendarRepeatRule({
const repeatRule = createTestEntity(CalendarRepeatRuleTypeRef, {
endType: EndType.UntilDate,
frequency: RepeatPeriod.DAILY,
interval: "1",
endValue: getDateInUTC("2023-03-04").getTime().toString(),
timeZone: zone,
excludedDates: [
createDateWrapper({ date: getDateInZone("2023-03-02T22:00") }),
createTestEntity(DateWrapperTypeRef, { date: getDateInZone("2023-03-02T22:00") }),
// 2023-03-03T22:00:00Z not excluded
],
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: getDateInZone("2023-03-02T22:00"),
endTime: getDateInZone("2023-03-02T23:00"),
repeatRule,
@ -1624,15 +1641,15 @@ o.spec("calendar utils tests", function () {
})
o("event with exclusions that are not occurrences", function () {
const repeatRule = createCalendarRepeatRule({
const repeatRule = createTestEntity(CalendarRepeatRuleTypeRef, {
endType: EndType.Count,
frequency: RepeatPeriod.DAILY,
interval: "2",
endValue: "2",
timeZone: zone,
excludedDates: [createDateWrapper({ date: new Date("2023-03-03T22:00:00Z") })],
excludedDates: [createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-03T22:00:00Z") })],
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-02T22:00:00Z"),
endTime: new Date("2023-03-02T23:00:00Z"),
repeatRule,
@ -1641,7 +1658,7 @@ o.spec("calendar utils tests", function () {
})
o("event with one occurrence (count), no exclusions", function () {
const repeatRule = createCalendarRepeatRule({
const repeatRule = createTestEntity(CalendarRepeatRuleTypeRef, {
endType: EndType.Count,
frequency: RepeatPeriod.DAILY,
interval: "1",
@ -1649,7 +1666,7 @@ o.spec("calendar utils tests", function () {
timeZone: zone,
excludedDates: [],
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-02T22:00:00Z"),
endTime: new Date("2023-03-02T23:00:00Z"),
repeatRule,
@ -1675,7 +1692,7 @@ o.spec("calendar utils tests", function () {
timeZone: zone,
excludedDates: [],
})
const progenitor = createCalendarEvent({
const progenitor = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-02T22:00:00Z"),
endTime: new Date("2023-03-02T23:00:00Z"),
repeatRule,
@ -1694,7 +1711,7 @@ o.spec("calendar utils tests", function () {
})
o("if no ownergroup but organizer, gets OWN", function () {
const event: Partial<CalendarEvent> = { organizer: createEncryptedMailAddress({ address: "my@address.to", name: "my" }) }
const event: Partial<CalendarEvent> = { organizer: createTestEntity(EncryptedMailAddressTypeRef, { address: "my@address.to", name: "my" }) }
const calendars = new Map()
const ownMailAddresses = ["my@address.to"]
const user: User = object()
@ -1703,7 +1720,7 @@ o.spec("calendar utils tests", function () {
})
o("if no ownergroup and not organizer, gets INVITE", function () {
const event: Partial<CalendarEvent> = { organizer: createEncryptedMailAddress({ address: "no@address.to", name: "my" }) }
const event: Partial<CalendarEvent> = { organizer: createTestEntity(EncryptedMailAddressTypeRef, { address: "no@address.to", name: "my" }) }
const calendars = new Map()
const ownMailAddresses = ["my@address.to"]
const user: User = object()
@ -1712,7 +1729,10 @@ o.spec("calendar utils tests", function () {
})
o("event in not any of our calendars gets SHARED_RO", function () {
const event: Partial<CalendarEvent> = { organizer: createEncryptedMailAddress({ address: "no@address.to", name: "my" }), _ownerGroup: "ownergroup" }
const event: Partial<CalendarEvent> = {
organizer: createTestEntity(EncryptedMailAddressTypeRef, { address: "no@address.to", name: "my" }),
_ownerGroup: "ownergroup",
}
const calendars = new Map()
const ownMailAddresses = ["my@address.to"]
const user: User = object()
@ -1721,11 +1741,14 @@ o.spec("calendar utils tests", function () {
})
o("event in rw-shared calendar w/o attendees gets SHARED_RW", function () {
const event: Partial<CalendarEvent> = { organizer: createEncryptedMailAddress({ address: "no@address.to", name: "my" }), _ownerGroup: "ownergroup" }
const event: Partial<CalendarEvent> = {
organizer: createTestEntity(EncryptedMailAddressTypeRef, { address: "no@address.to", name: "my" }),
_ownerGroup: "ownergroup",
}
const calendars = new Map()
calendars.set("ownergroup", {
shared: true,
group: createGroup({
group: createTestEntity(GroupTypeRef, {
_id: "calendarGroup",
type: GroupType.Calendar,
user: "otherUser",
@ -1735,7 +1758,7 @@ o.spec("calendar utils tests", function () {
const user: User = object()
user.accountType = AccountType.PAID
user.memberships = [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
group: "calendarGroup",
capability: ShareCapability.Write,
}),
@ -1746,14 +1769,18 @@ o.spec("calendar utils tests", function () {
o("event in rw-shared calendar w attendees gets LOCKED", function () {
const event: Partial<CalendarEvent> = {
organizer: createEncryptedMailAddress({ address: "no@address.to", name: "my" }),
organizer: createTestEntity(EncryptedMailAddressTypeRef, { address: "no@address.to", name: "my" }),
_ownerGroup: "ownergroup",
attendees: [createCalendarEventAttendee({ address: createEncryptedMailAddress({ address: "bla", name: "blabla" }) })],
attendees: [
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, { address: "bla", name: "blabla" }),
}),
],
}
const calendars = new Map()
calendars.set("ownergroup", {
shared: true,
group: createGroup({
group: createTestEntity(GroupTypeRef, {
_id: "calendarGroup",
type: GroupType.Calendar,
user: "otherUser",
@ -1763,7 +1790,7 @@ o.spec("calendar utils tests", function () {
const user: User = object()
user.accountType = AccountType.PAID
user.memberships = [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
group: "calendarGroup",
capability: ShareCapability.Write,
}),
@ -1774,14 +1801,18 @@ o.spec("calendar utils tests", function () {
o("event with ownergroup in own calendar where we're organizer gets OWN", function () {
const event: Partial<CalendarEvent> = {
organizer: createEncryptedMailAddress({ address: "my@address.to", name: "my" }),
organizer: createTestEntity(EncryptedMailAddressTypeRef, { address: "my@address.to", name: "my" }),
_ownerGroup: "ownergroup",
attendees: [createCalendarEventAttendee({ address: createEncryptedMailAddress({ address: "bla", name: "blabla" }) })],
attendees: [
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, { address: "bla", name: "blabla" }),
}),
],
}
const calendars = new Map()
calendars.set("ownergroup", {
shared: false,
group: createGroup({
group: createTestEntity(GroupTypeRef, {
_id: "calendarGroup",
type: GroupType.Calendar,
user: "userId",
@ -1798,14 +1829,16 @@ o.spec("calendar utils tests", function () {
o("event with ownergroup in ro-shared calendar gets shared_ro", function () {
const event: Partial<CalendarEvent> = {
organizer: createEncryptedMailAddress({ address: "no@address.to", name: "my" }),
organizer: createTestEntity(EncryptedMailAddressTypeRef, { address: "no@address.to", name: "my" }),
_ownerGroup: "ownergroup",
attendees: [createCalendarEventAttendee({ address: createEncryptedMailAddress({ address: "bla", name: "blabla" }) })],
attendees: [
createTestEntity(CalendarEventAttendeeTypeRef, { address: createTestEntity(EncryptedMailAddressTypeRef, { address: "bla", name: "blabla" }) }),
],
}
const calendars = new Map()
calendars.set("ownergroup", {
shared: true,
group: createGroup({
group: createTestEntity(GroupTypeRef, {
_id: "calendarGroup",
type: GroupType.Calendar,
user: "otherUser",
@ -1815,7 +1848,7 @@ o.spec("calendar utils tests", function () {
const user: User = object()
user.accountType = AccountType.PAID
user.memberships = [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
group: "calendarGroup",
capability: ShareCapability.Read,
}),
@ -1826,14 +1859,16 @@ o.spec("calendar utils tests", function () {
o("event with ownergroup in own calendar and a different organizer gets INVITE", function () {
const event: Partial<CalendarEvent> = {
organizer: createEncryptedMailAddress({ address: "other@address.to", name: "other" }),
organizer: createTestEntity(EncryptedMailAddressTypeRef, { address: "other@address.to", name: "other" }),
_ownerGroup: "ownergroup",
attendees: [createCalendarEventAttendee({ address: createEncryptedMailAddress({ address: "bla", name: "blabla" }) })],
attendees: [
createTestEntity(CalendarEventAttendeeTypeRef, { address: createTestEntity(EncryptedMailAddressTypeRef, { address: "bla", name: "blabla" }) }),
],
}
const calendars = new Map()
calendars.set("ownergroup", {
shared: false,
group: createGroup({
group: createTestEntity(GroupTypeRef, {
_id: "calendarGroup",
type: GroupType.Calendar,
user: "userId",

View file

@ -14,17 +14,23 @@ import {
import { CalendarNotificationSender } from "../../../../src/calendar/date/CalendarNotificationSender.js"
import { CalendarModel } from "../../../../src/calendar/model/CalendarModel.js"
import {
CalendarEventAttendeeTypeRef,
CalendarEventTypeRef,
createCalendarEvent,
createCalendarEventAttendee,
createEncryptedMailAddress,
createMailboxProperties,
EncryptedMailAddressTypeRef,
MailboxGroupRootTypeRef,
MailboxProperties,
MailboxPropertiesTypeRef,
MailBoxTypeRef,
} from "../../../../src/api/entities/tutanota/TypeRefs.js"
import { EntityClient } from "../../../../src/api/common/EntityClient.js"
import { calendars, getDateInZone, makeUserController, otherAddress, ownerAddress, ownerAlias, ownerId, ownerMailAddress } from "../CalendarTestUtils.js"
import {
AlarmInfoTypeRef,
CalendarEventRefTypeRef,
createAlarmInfo,
createCalendarEventRef,
createDateWrapper,
@ -32,7 +38,11 @@ import {
createRepeatRule,
createUserAlarmInfo,
DateWrapper,
DateWrapperTypeRef,
GroupInfoTypeRef,
GroupTypeRef,
RepeatRuleTypeRef,
UserAlarmInfoTypeRef,
} from "../../../../src/api/entities/sys/TypeRefs.js"
import { clone, identity, noOp } from "@tutao/tutanota-utils"
import { RecipientsModel, ResolvableRecipient, ResolveMode } from "../../../../src/api/main/RecipientsModel.js"
@ -68,7 +78,7 @@ o.spec("CalendarEventModelTest", function () {
o.spec("integration tests", function () {
o("doing no edit operation on an existing event updates it as expected, no updates.", async function () {
// this test case is insane and only serves as a warning example to not do such things.
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
sequence: "0",
_id: ["eventListId", "eventElementId"],
_ownerGroup: "ownCalendar",
@ -81,7 +91,7 @@ o.spec("CalendarEventModelTest", function () {
startTime: new Date("2023-04-27T15:00:00.000Z"),
invitedConfidentially: false,
endTime: new Date("2023-04-27T15:30:00.000Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
interval: "10",
_id: "repeatRuleId",
endType: EndType.Count,
@ -92,11 +102,11 @@ o.spec("CalendarEventModelTest", function () {
organizer: ownerAddress,
alarmInfos: [["alarmListId", "alarmElementId"]],
attendees: [
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: ownerAddress,
status: CalendarAttendeeStatus.ACCEPTED,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: otherAddress,
status: CalendarAttendeeStatus.ACCEPTED,
}),
@ -107,12 +117,12 @@ o.spec("CalendarEventModelTest", function () {
const userController = makeUserController([ownerAlias.address], AccountType.PAID, ownerMailAddress, true)
when(logins.getUserController()).thenReturn(userController)
when(calendarModel.loadAlarms(event.alarmInfos, userController.user)).thenResolve([
createUserAlarmInfo({
createTestEntity(UserAlarmInfoTypeRef, {
_id: event.alarmInfos[0],
alarmInfo: createAlarmInfo({
alarmInfo: createTestEntity(AlarmInfoTypeRef, {
alarmIdentifier: "alarmIdentifier",
trigger: "5M",
calendarRef: createCalendarEventRef({
calendarRef: createTestEntity(CalendarEventRefTypeRef, {
elementId: event._id[1],
listId: event._id[0],
}),
@ -132,12 +142,12 @@ o.spec("CalendarEventModelTest", function () {
mailbox: createTestEntity(MailBoxTypeRef),
folders: new FolderSystem([]),
mailGroupInfo: createTestEntity(GroupInfoTypeRef),
mailGroup: createGroup({
mailGroup: createTestEntity(GroupTypeRef, {
user: ownerId,
}),
mailboxGroupRoot: createTestEntity(MailboxGroupRootTypeRef),
}
const mailboxProperties: MailboxProperties = createMailboxProperties({})
const mailboxProperties: MailboxProperties = createTestEntity(MailboxPropertiesTypeRef, {})
const sendModelFac: () => SendMailModel = func<() => SendMailModel>()
const model = await makeCalendarEventModel(
CalendarOperation.EditAll,
@ -180,13 +190,13 @@ o.spec("CalendarEventModelTest", function () {
})
o.spec("eventHasChanged", function () {
const fixedOrganizer = createEncryptedMailAddress({
const fixedOrganizer = createTestEntity(EncryptedMailAddressTypeRef, {
address: "moo@d.de",
name: "bla",
})
const att = (a, n, s) =>
createCalendarEventAttendee({
address: createEncryptedMailAddress({ address: a, name: n }),
createTestEntity(CalendarEventAttendeeTypeRef, {
address: createTestEntity(EncryptedMailAddressTypeRef, { address: a, name: n }),
status: s,
})
// attr, now, previous, expected, msg
@ -200,9 +210,27 @@ o.spec("CalendarEventModelTest", function () {
["endTime", getDateInZone("2023-05-26"), getDateInZone("2023-05-27"), true],
["uid", "newUid", "oldUid", true],
["organizer", fixedOrganizer, fixedOrganizer, false, "same object in organizer"],
["organizer", fixedOrganizer, createEncryptedMailAddress({ address: "moo@d.de", name: "bla" }), false, "same organizer, different object"],
["organizer", fixedOrganizer, createEncryptedMailAddress({ address: "moo@d.de", name: "blabla" }), false, "different address, same name"],
["organizer", fixedOrganizer, createEncryptedMailAddress({ address: "moo@d.io", name: "bla" }), true, "same name, different address"],
[
"organizer",
fixedOrganizer,
createTestEntity(EncryptedMailAddressTypeRef, { address: "moo@d.de", name: "bla" }),
false,
"same organizer, different object",
],
[
"organizer",
fixedOrganizer,
createTestEntity(EncryptedMailAddressTypeRef, { address: "moo@d.de", name: "blabla" }),
false,
"different address, same name",
],
[
"organizer",
fixedOrganizer,
createTestEntity(EncryptedMailAddressTypeRef, { address: "moo@d.io", name: "bla" }),
true,
"same name, different address",
],
["attendees", [], [], false, "no attendees in either event"],
[
"attendees",
@ -233,7 +261,7 @@ o.spec("CalendarEventModelTest", function () {
o(`${attr} changed -> ${expected}`, function () {
// createCalendarEvent will create events with a startTime and endTime created by "new Date()",
// which is not repeatable, so we only do it once.
const template = createCalendarEvent({ [attr]: previous })
const template = createTestEntity(CalendarEventTypeRef, { [attr]: previous })
const copy = Object.assign({}, template, { [attr]: now })
o(eventHasChanged(copy, template)).equals(expected)(msg ?? attr)
o(eventHasChanged(copy, clone(copy))).equals(false)(`do not change ${msg}`)
@ -241,12 +269,12 @@ o.spec("CalendarEventModelTest", function () {
}
o("same object -> false", function () {
const event = createCalendarEvent({})
const event = createTestEntity(CalendarEventTypeRef, {})
o(eventHasChanged(event, event)).equals(false)
})
})
const dw = (d) => createDateWrapper({ date: getDateInZone(d) })
const dw = (d) => createTestEntity(DateWrapperTypeRef, { date: getDateInZone(d) })
o.spec("areRepeatRulesEqual", function () {
// property, now, previous, expected, msg
const cases = [
@ -261,12 +289,16 @@ o.spec("CalendarEventModelTest", function () {
for (const [attr, now, previous, expected, msg] of cases) {
o(`${attr} changed -> ${expected}`, function () {
o(areRepeatRulesEqual(createRepeatRule({ [attr]: now }), createRepeatRule({ [attr]: previous }))).equals(expected)(msg ?? attr)
o(areRepeatRulesEqual(createRepeatRule({ [attr]: now }), createRepeatRule({ [attr]: now }))).equals(true)(`do not change ${msg}`)
o(areRepeatRulesEqual(createTestEntity(RepeatRuleTypeRef, { [attr]: now }), createTestEntity(RepeatRuleTypeRef, { [attr]: previous }))).equals(
expected,
)(msg ?? attr)
o(areRepeatRulesEqual(createTestEntity(RepeatRuleTypeRef, { [attr]: now }), createTestEntity(RepeatRuleTypeRef, { [attr]: now }))).equals(true)(
`do not change ${msg}`,
)
})
}
o("same object -> true", function () {
const r1 = createRepeatRule({})
const r1 = createTestEntity(RepeatRuleTypeRef, {})
o(areRepeatRulesEqual(r1, r1)).equals(true)
})
})

View file

@ -4,9 +4,10 @@ import { getEventWithDefaultTimes, isAllDayEvent } from "../../../../src/api/com
import { Time } from "../../../../src/calendar/date/Time.js"
import { CalendarEventWhenModel, getDefaultEndCountValue } from "../../../../src/calendar/date/eventeditor/CalendarEventWhenModel.js"
import { EndType, RepeatPeriod } from "../../../../src/api/common/TutanotaConstants.js"
import { createDateWrapper, createRepeatRule } from "../../../../src/api/entities/sys/TypeRefs.js"
import { CalendarEvent, createCalendarEvent } from "../../../../src/api/entities/tutanota/TypeRefs.js"
import { DateWrapperTypeRef, RepeatRuleTypeRef } from "../../../../src/api/entities/sys/TypeRefs.js"
import { CalendarEvent, CalendarEventTypeRef } from "../../../../src/api/entities/tutanota/TypeRefs.js"
import { DateTime } from "luxon"
import { createTestEntity } from "../../TestUtils.js"
o.spec("CalendarEventWhenModel", function () {
const getModelBerlin = (initialValues: Partial<CalendarEvent>) => new CalendarEventWhenModel(initialValues, "Europe/Berlin", noOp)
@ -335,7 +336,7 @@ o.spec("CalendarEventWhenModel", function () {
model.repeatPeriod = RepeatPeriod.DAILY
o(model.repeatPeriod).equals(RepeatPeriod.DAILY)
o(model.result.repeatRule).deepEquals(
createRepeatRule({
createTestEntity(RepeatRuleTypeRef, {
interval: "1",
endType: EndType.Never,
endValue: "1",
@ -350,7 +351,7 @@ o.spec("CalendarEventWhenModel", function () {
const model = getModelBerlin({
startTime: new Date("2023-04-27T00:00:00.000Z"),
endTime: new Date("2023-04-28T00:00:00.000Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
interval: "1",
endType: EndType.Never,
endValue: "1",
@ -377,7 +378,7 @@ o.spec("CalendarEventWhenModel", function () {
const model = getModelBerlin({
startTime: new Date("2023-04-27T00:00:00.000Z"),
endTime: new Date("2023-04-28T00:00:00.000Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
interval: "1",
endType: EndType.Never,
endValue: "1",
@ -423,7 +424,7 @@ o.spec("CalendarEventWhenModel", function () {
const model = getModelBerlin({
startTime: new Date("2023-04-27T00:00:00.000Z"),
endTime: new Date("2023-04-28T00:00:00.000Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
interval: "1",
endType: EndType.Count,
endValue: "42",
@ -442,7 +443,7 @@ o.spec("CalendarEventWhenModel", function () {
const model = getModelBerlin({
startTime: new Date("2023-04-27T00:00:00.000Z"),
endTime: new Date("2023-04-28T00:00:00.000Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
interval: "1",
endType: EndType.UntilDate,
endValue: new Date("2023-04-30T00:00:00.000Z").getTime().toString(),
@ -464,7 +465,7 @@ o.spec("CalendarEventWhenModel", function () {
const model = getModelBerlin({
startTime: new Date("2023-04-27T00:00:00.000Z"),
endTime: new Date("2023-04-28T00:00:00.000Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
interval: "10",
endType: EndType.Count,
endValue: "10",
@ -482,7 +483,7 @@ o.spec("CalendarEventWhenModel", function () {
const model = getModelBerlin({
startTime: new Date("2023-04-27T00:00:00.000Z"),
endTime: new Date("2023-04-28T00:00:00.000Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
interval: "10",
endType: EndType.Count,
endValue: "10",
@ -501,10 +502,10 @@ o.spec("CalendarEventWhenModel", function () {
o.spec("deleteExcludedDates", function () {
o("clears the array of excluded dates", async function () {
const model = await getModelBerlin(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-13T00:00:00Z"),
repeatRule: createRepeatRule({
excludedDates: [createDateWrapper({ date: new Date("2023-03-13T00:00:00Z") })],
repeatRule: createTestEntity(RepeatRuleTypeRef, {
excludedDates: [createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-13T00:00:00Z") })],
}),
}),
)
@ -515,12 +516,12 @@ o.spec("CalendarEventWhenModel", function () {
})
o("end occurrence changed to smaller -> delete exclusions", async function () {
const model = await getModelBerlin(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-13T00:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
endType: EndType.Count,
endValue: "42",
excludedDates: [createDateWrapper({ date: new Date("2023-03-13T00:00:00Z") })],
excludedDates: [createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-13T00:00:00Z") })],
}),
}),
)
@ -530,12 +531,12 @@ o.spec("CalendarEventWhenModel", function () {
})
o("end occurrence changed to bigger -> delete exclusions", async function () {
const model = await getModelBerlin(
createCalendarEvent({
createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-13T00:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
endType: EndType.Count,
endValue: "42",
excludedDates: [createDateWrapper({ date: new Date("2023-03-13T00:00:00Z") })],
excludedDates: [createTestEntity(DateWrapperTypeRef, { date: new Date("2023-03-13T00:00:00Z") })],
}),
}),
)
@ -545,14 +546,14 @@ o.spec("CalendarEventWhenModel", function () {
})
o("interval changes delete exclusions", async function () {
const excludedDates = [new Date("2023-03-13T00:00:00Z")]
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-13T00:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
frequency: "1",
interval: "1",
endType: EndType.Count,
endValue: "10",
excludedDates: excludedDates.map((date) => createDateWrapper({ date })),
excludedDates: excludedDates.map((date) => createTestEntity(DateWrapperTypeRef, { date })),
timeZone: "Europe/Berlin",
}),
})
@ -567,14 +568,14 @@ o.spec("CalendarEventWhenModel", function () {
})
o("frequency changes delete exclusions", async function () {
const excludedDates = [new Date("2023-03-13T00:00:00Z")]
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-03-13T00:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
frequency: "1",
interval: "1",
endType: EndType.Count,
endValue: "10",
excludedDates: excludedDates.map((date) => createDateWrapper({ date })),
excludedDates: excludedDates.map((date) => createTestEntity(DateWrapperTypeRef, { date })),
timeZone: "Europe/Berlin",
}),
})
@ -589,15 +590,15 @@ o.spec("CalendarEventWhenModel", function () {
o("repeat end date changes delete exclusions", async function () {
const excludedDates = [new Date("2023-04-13T15:00:00Z")]
const originalUntilDate = new Date("2023-05-13T00:00:00Z")
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-01-13T15:00:00Z"),
endTime: new Date("2023-01-13T20:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
frequency: RepeatPeriod.DAILY,
interval: "1",
endType: EndType.UntilDate,
endValue: originalUntilDate.getTime().toString(),
excludedDates: excludedDates.map((date) => createDateWrapper({ date })),
excludedDates: excludedDates.map((date) => createTestEntity(DateWrapperTypeRef, { date })),
timeZone: "Europe/Berlin",
}),
})
@ -614,15 +615,15 @@ o.spec("CalendarEventWhenModel", function () {
o("repeat end date changes delete exclusions, all-day events", function () {
const excludedDates = [new Date("2023-04-13T15:00:00Z")]
const originalUntilDate = new Date("2023-05-13T00:00:00Z")
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-01-13T00:00:00Z"),
endTime: new Date("2023-01-14T00:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
frequency: RepeatPeriod.DAILY,
interval: "1",
endType: EndType.UntilDate,
endValue: originalUntilDate.getTime().toString(),
excludedDates: excludedDates.map((date) => createDateWrapper({ date })),
excludedDates: excludedDates.map((date) => createTestEntity(DateWrapperTypeRef, { date })),
timeZone: "Europe/Berlin",
}),
})
@ -640,15 +641,15 @@ o.spec("CalendarEventWhenModel", function () {
o("time zone changes do not delete exclusions", async function () {
const excludedDates = [new Date("2023-04-13T15:00:00Z")]
const originalUntilDate = new Date("2023-05-13T00:00:00Z")
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-01-13T00:00:00Z"),
endTime: new Date("2023-01-14T00:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
frequency: RepeatPeriod.DAILY,
interval: "1",
endType: EndType.UntilDate,
endValue: originalUntilDate.getTime().toString(),
excludedDates: excludedDates.map((date) => createDateWrapper({ date })),
excludedDates: excludedDates.map((date) => createTestEntity(DateWrapperTypeRef, { date })),
timeZone: "Asia/Krasnoyarsk",
}),
})
@ -661,7 +662,7 @@ o.spec("CalendarEventWhenModel", function () {
})
o.spec("excludeDate", function () {
o("no exclusion is added if event has no repeat rule", async function () {
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-01-13T00:00:00Z"),
endTime: new Date("2023-01-14T00:00:00Z"),
repeatRule: null,
@ -672,10 +673,10 @@ o.spec("CalendarEventWhenModel", function () {
o(model.result.repeatRule).equals(null)
})
o("adding two exclusions in reverse order sorts them", async function () {
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-01-13T00:00:00Z"),
endTime: new Date("2023-01-14T00:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
frequency: RepeatPeriod.DAILY,
interval: "1",
endType: EndType.Never,
@ -688,14 +689,14 @@ o.spec("CalendarEventWhenModel", function () {
model.excludeDate(exclusions[1])
model.excludeDate(exclusions[0])
o(model.result.repeatRule?.excludedDates).deepEquals(exclusions.map((date) => createDateWrapper({ date })))
o(model.result.repeatRule?.excludedDates).deepEquals(exclusions.map((date) => createTestEntity(DateWrapperTypeRef, { date })))
o(model.excludedDates).deepEquals(exclusions)
})
o("adding two exclusions in order sorts them", async function () {
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-01-13T00:00:00Z"),
endTime: new Date("2023-01-14T00:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
frequency: RepeatPeriod.DAILY,
interval: "1",
endType: EndType.Never,
@ -708,14 +709,14 @@ o.spec("CalendarEventWhenModel", function () {
model.excludeDate(exclusions[0])
model.excludeDate(exclusions[1])
o(model.result.repeatRule?.excludedDates).deepEquals(exclusions.map((date) => createDateWrapper({ date })))
o(model.result.repeatRule?.excludedDates).deepEquals(exclusions.map((date) => createTestEntity(DateWrapperTypeRef, { date })))
o(model.excludedDates).deepEquals(exclusions)
})
o("adding the same exclusion multiple times deduplicates them", async function () {
const event = createCalendarEvent({
const event = createTestEntity(CalendarEventTypeRef, {
startTime: new Date("2023-01-13T00:00:00Z"),
endTime: new Date("2023-01-14T00:00:00Z"),
repeatRule: createRepeatRule({
repeatRule: createTestEntity(RepeatRuleTypeRef, {
frequency: RepeatPeriod.DAILY,
interval: "1",
endType: EndType.Never,
@ -728,7 +729,7 @@ o.spec("CalendarEventWhenModel", function () {
model.excludeDate(exclusion)
model.excludeDate(exclusion)
o(model.result.repeatRule?.excludedDates).deepEquals([createDateWrapper({ date: exclusion })])
o(model.result.repeatRule?.excludedDates).deepEquals([createTestEntity(DateWrapperTypeRef, { date: exclusion })])
o(model.excludedDates).deepEquals([exclusion])
})
})

View file

@ -1,11 +1,19 @@
import o from "@tutao/otest"
import { CalendarEvent, createCalendarEvent, createCalendarEventAttendee, createContact } from "../../../../src/api/entities/tutanota/TypeRefs.js"
import {
CalendarEvent,
CalendarEventAttendeeTypeRef,
CalendarEventTypeRef,
ContactTypeRef,
createCalendarEvent,
createCalendarEventAttendee,
createContact,
} from "../../../../src/api/entities/tutanota/TypeRefs.js"
import { CalendarEventWhoModel } from "../../../../src/calendar/date/eventeditor/CalendarEventWhoModel.js"
import { matchers, object, verify, when } from "testdouble"
import { RecipientsModel } from "../../../../src/api/main/RecipientsModel.js"
import { Recipient, RecipientType } from "../../../../src/api/common/recipients/Recipient.js"
import { AccountType, CalendarAttendeeStatus, ShareCapability } from "../../../../src/api/common/TutanotaConstants.js"
import { createUser } from "../../../../src/api/entities/sys/TypeRefs.js"
import { createUser, UserTypeRef } from "../../../../src/api/entities/sys/TypeRefs.js"
import { SendMailModel } from "../../../../src/mail/editor/SendMailModel.js"
import { UserController } from "../../../../src/api/main/UserController.js"
import { CalendarOperation, EventType } from "../../../../src/calendar/date/eventeditor/CalendarEventModel.js"
@ -29,6 +37,7 @@ import {
import { assertNotNull, neverNull } from "@tutao/tutanota-utils"
import { RecipientField } from "../../../../src/mail/model/MailUtils.js"
import { ProgrammingError } from "../../../../src/api/common/error/ProgrammingError.js"
import { createTestEntity } from "../../TestUtils.js"
o.spec("CalendarEventWhoModel", function () {
const passwordStrengthModel = () => 1
@ -152,18 +161,18 @@ o.spec("CalendarEventWhoModel", function () {
o.spec("invite capabilities for different events", function () {
o("invite in our own calendar can only modify own attendance", async function () {
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
summary: "existing event",
startTime: new Date(2020, 4, 26, 12),
endTime: new Date(2020, 4, 26, 13),
organizer: otherAddress,
_ownerGroup: "ownCalendar",
attendees: [
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: ownerAddress,
status: CalendarAttendeeStatus.ACCEPTED,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: otherAddress,
}),
],
@ -178,18 +187,18 @@ o.spec("CalendarEventWhoModel", function () {
o("existing normal event in writable calendar can not modify guests", async function () {
const userController = makeUserController()
addCapability(userController.user, "sharedCalendar", ShareCapability.Write)
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
summary: "existing event",
startTime: new Date(2020, 4, 26, 12),
endTime: new Date(2020, 4, 26, 13),
organizer: otherAddress,
_ownerGroup: "sharedCalendar",
attendees: [
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: ownerAddress,
status: CalendarAttendeeStatus.ACCEPTED,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: otherAddress,
}),
],
@ -203,17 +212,17 @@ o.spec("CalendarEventWhoModel", function () {
o("for an invite in writable calendar, we cannot modify guests", async function () {
const userController = makeUserController()
addCapability(userController.user, "sharedCalendar", ShareCapability.Write)
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
summary: "existing event",
startTime: new Date(2020, 4, 26, 12),
endTime: new Date(2020, 4, 26, 13),
organizer: otherAddress,
_ownerGroup: "sharedCalendar",
attendees: [
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: otherAddress,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: otherAddress2,
}),
],
@ -225,7 +234,7 @@ o.spec("CalendarEventWhoModel", function () {
o("in readonly calendar, cannot modify guests", async function () {
const userController = makeUserController()
addCapability(userController.user, "sharedCalendar", ShareCapability.Read)
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_ownerGroup: "sharedCalendar",
})
const model = getOldSharedModel(existingEvent, EventType.SHARED_RO)
@ -235,17 +244,17 @@ o.spec("CalendarEventWhoModel", function () {
o("in writable calendar w/ guests, we cannot modify guests", async function () {
const userController = makeUserController()
addCapability(userController.user, "sharedCalendar", ShareCapability.Write)
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
summary: "existing event",
startTime: new Date(2020, 4, 26, 12),
endTime: new Date(2020, 4, 26, 13),
organizer: otherAddress,
_ownerGroup: "sharedCalendar",
attendees: [
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: otherAddress,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: ownerAddress,
}),
],
@ -258,7 +267,10 @@ o.spec("CalendarEventWhoModel", function () {
o.spec("adding and removing attendees", function () {
o("adding another alias on your own event replaces the old attendee and updates the organizer", async function () {
const model = getNewModel({
attendees: [createCalendarEventAttendee({ address: ownAddresses[0] }), createCalendarEventAttendee({ address: otherAddress })],
attendees: [
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownAddresses[0] }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress }),
],
organizer: ownAddresses[0],
})
@ -280,14 +292,17 @@ o.spec("CalendarEventWhoModel", function () {
o(result.cancelModel).equals(null)
o(result.responseModel).equals(null)
o(result.attendees).deepEquals([
createCalendarEventAttendee({ address: ownerAlias, status: CalendarAttendeeStatus.ACCEPTED }),
createCalendarEventAttendee({ address: otherAddress, status: CalendarAttendeeStatus.ADDED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownerAlias, status: CalendarAttendeeStatus.ACCEPTED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress, status: CalendarAttendeeStatus.ADDED }),
])("the result contains all attendees including the organizer")
o(result.organizer).deepEquals(ownerAlias)
})
o("setting multiple ownAddresses correctly gives the possible organizers", function () {
const model = getNewModel({
attendees: [createCalendarEventAttendee({ address: ownAddresses[0] }), createCalendarEventAttendee({ address: otherAddress })],
attendees: [
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownAddresses[0] }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress }),
],
organizer: ownAddresses[0],
})
o(model.possibleOrganizers).deepEquals([ownerAddress, ownerAlias])
@ -324,7 +339,10 @@ o.spec("CalendarEventWhoModel", function () {
})
o("trying to remove the organizer while there are other attendees does nothing", function () {
const model = getNewModel({
attendees: [createCalendarEventAttendee({ address: ownAddresses[0] }), createCalendarEventAttendee({ address: otherAddress })],
attendees: [
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownAddresses[0] }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress }),
],
organizer: ownerAddress,
})
model.removeAttendee(ownerAddress.address)
@ -335,8 +353,8 @@ o.spec("CalendarEventWhoModel", function () {
o("getting the result on an old model is idempotent", function () {
const model = getOldModel({
attendees: [
createCalendarEventAttendee({ address: ownAddresses[0], status: CalendarAttendeeStatus.ACCEPTED }),
createCalendarEventAttendee({ address: otherAddress, status: CalendarAttendeeStatus.ACCEPTED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownAddresses[0], status: CalendarAttendeeStatus.ACCEPTED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress, status: CalendarAttendeeStatus.ACCEPTED }),
],
organizer: ownerAddress,
})
@ -347,8 +365,8 @@ o.spec("CalendarEventWhoModel", function () {
o("removing an attendee while there are other attendees removes only that attendee", async function () {
const model = getOldModel({
attendees: [
createCalendarEventAttendee({ address: ownAddresses[0], status: CalendarAttendeeStatus.ACCEPTED }),
createCalendarEventAttendee({ address: otherAddress }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownAddresses[0], status: CalendarAttendeeStatus.ACCEPTED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress }),
],
organizer: ownerAddress,
})
@ -357,24 +375,24 @@ o.spec("CalendarEventWhoModel", function () {
await model.recipientsSettled
const resultBeforeRemove = model.result
o(resultBeforeRemove.attendees).deepEquals([
createCalendarEventAttendee({ address: ownerAddress, status: CalendarAttendeeStatus.ACCEPTED }),
createCalendarEventAttendee({ address: otherAddress, status: CalendarAttendeeStatus.ADDED }),
createCalendarEventAttendee({ address: otherAddress2, status: CalendarAttendeeStatus.ADDED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownerAddress, status: CalendarAttendeeStatus.ACCEPTED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress, status: CalendarAttendeeStatus.ADDED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress2, status: CalendarAttendeeStatus.ADDED }),
])("there are three attendees in the event")
o(resultBeforeRemove.organizer).deepEquals(ownerAddress)
model.removeAttendee(otherAddress.address)
const result = model.result
o(result.attendees).deepEquals([
createCalendarEventAttendee({ address: ownerAddress, status: CalendarAttendeeStatus.ACCEPTED }),
createCalendarEventAttendee({ address: otherAddress2, status: CalendarAttendeeStatus.ADDED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownerAddress, status: CalendarAttendeeStatus.ACCEPTED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress2, status: CalendarAttendeeStatus.ADDED }),
])
o(result.organizer).deepEquals(ownerAddress)
})
o("setting external passwords is reflected in the getters and result", async function () {
const model = getNewModel({
attendees: [
createCalendarEventAttendee({ address: ownAddresses[0] }),
createCalendarEventAttendee({ address: otherAddress, status: CalendarAttendeeStatus.NEEDS_ACTION }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownAddresses[0] }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress, status: CalendarAttendeeStatus.NEEDS_ACTION }),
],
organizer: ownerAddress,
invitedConfidentially: true,
@ -403,11 +421,11 @@ o.spec("CalendarEventWhoModel", function () {
o(model.getPresharedPassword(otherAddress.address)).deepEquals({ password: "otherPassword", strength: 1 })
const { attendees } = model.result
o(attendees).deepEquals([
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: ownerAddress,
status: CalendarAttendeeStatus.ADDED,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
address: otherAddress,
status: CalendarAttendeeStatus.NEEDS_ACTION,
}),
@ -424,9 +442,9 @@ o.spec("CalendarEventWhoModel", function () {
o("organizer is replaced with ourselves when an own event with someone else as organizer is opened", function () {
const model = getNewModel({
attendees: [
createCalendarEventAttendee({ address: ownAddresses[0], status: CalendarAttendeeStatus.ACCEPTED }),
createCalendarEventAttendee({ address: otherAddress, status: CalendarAttendeeStatus.ACCEPTED }),
createCalendarEventAttendee({ address: otherAddress2, status: CalendarAttendeeStatus.NEEDS_ACTION }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: ownAddresses[0], status: CalendarAttendeeStatus.ACCEPTED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress, status: CalendarAttendeeStatus.ACCEPTED }),
createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress2, status: CalendarAttendeeStatus.NEEDS_ACTION }),
],
organizer: otherAddress,
})
@ -439,21 +457,21 @@ o.spec("CalendarEventWhoModel", function () {
const sendModels: Array<SendMailModel> = [object<SendMailModel>("first"), object<SendMailModel>("second"), object<SendMailModel>("third")]
const userController = makeUserController([], AccountType.PAID)
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_ownerGroup: "ownCalendar",
startTime: getDateInZone("2020-06-01"),
endTime: getDateInZone("2020-06-02"),
organizer: ownerAddress,
attendees: [
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.NEEDS_ACTION,
address: ownerAddress,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.NEEDS_ACTION,
address: otherAddress2,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.NEEDS_ACTION,
address: thirdAddress,
}),
@ -475,7 +493,7 @@ o.spec("CalendarEventWhoModel", function () {
)
model.shouldSendUpdates = true
model.removeAttendee(otherAddress2.address)
model.addAttendee(otherAddress.address, createContact({ nickname: otherAddress.name }))
model.addAttendee(otherAddress.address, createTestEntity(ContactTypeRef, { nickname: otherAddress.name }))
const result = model.result
// this is not an invite to us, so we do not respond
o(result.responseModel).equals(null)
@ -491,17 +509,17 @@ o.spec("CalendarEventWhoModel", function () {
o("adding attendees on new event correctly creates invite model", function () {
const sendModels: Array<SendMailModel> = [object()]
const userController = makeUserController([], AccountType.PAID)
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_ownerGroup: "ownCalendar",
startTime: new Date(2020, 5, 1),
endTime: new Date(2020, 5, 2),
organizer: ownerAddress,
attendees: [
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.NEEDS_ACTION,
address: ownerAddress,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.NEEDS_ACTION,
address: otherAddress2,
}),
@ -521,7 +539,7 @@ o.spec("CalendarEventWhoModel", function () {
passwordStrengthModel,
() => sendModels.pop()!,
)
model.addAttendee(otherAddress.address, createContact({ nickname: otherAddress.name }))
model.addAttendee(otherAddress.address, createTestEntity(ContactTypeRef, { nickname: otherAddress.name }))
const result = model.result
o(result.responseModel).equals(null)
o(sendModels.length).equals(0)
@ -535,7 +553,7 @@ o.spec("CalendarEventWhoModel", function () {
o.spec("calendar selection", function () {
o.spec("getAvailableCalendars", function () {
o("it returns the shared calendars we have write access to when there are no attendees", function () {
userController.user = createUser({ _id: "ownerId" })
userController.user = createTestEntity(UserTypeRef, { _id: "ownerId" })
// add it as a writable calendar so that we see that it's filtered out
addCapability(userController.user, "sharedCalendar", ShareCapability.Write)
const model = getNewModel({})
@ -543,7 +561,7 @@ o.spec("CalendarEventWhoModel", function () {
})
o("it returns only the calendars we have write access to", function () {
userController.user = createUser({ _id: "ownerId" })
userController.user = createTestEntity(UserTypeRef, { _id: "ownerId" })
// add it as a writable calendar so that we see that it's filtered out
addCapability(userController.user, "sharedCalendar", ShareCapability.Read)
const model = getNewModel({})
@ -551,7 +569,7 @@ o.spec("CalendarEventWhoModel", function () {
})
o("it returns only own calendars after adding attendees to an existing event", function () {
userController.user = createUser({ _id: "ownerId" })
userController.user = createTestEntity(UserTypeRef, { _id: "ownerId" })
// add it as a writable calendar so that we see that it's filtered out
addCapability(userController.user, "sharedCalendar", ShareCapability.Write)
const model = getOldModel({})
@ -560,17 +578,17 @@ o.spec("CalendarEventWhoModel", function () {
})
o("it returns only own calendars for existing own event with attendees ", function () {
userController.user = createUser({ _id: "ownerId" })
userController.user = createTestEntity(UserTypeRef, { _id: "ownerId" })
// add it as a writable calendar so that we see that it's filtered out
addCapability(userController.user, "sharedCalendar", ShareCapability.Write)
const model = getOldModel({
attendees: [createCalendarEventAttendee({ address: otherAddress, status: CalendarAttendeeStatus.NEEDS_ACTION })],
attendees: [createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress, status: CalendarAttendeeStatus.NEEDS_ACTION })],
})
o(model.getAvailableCalendars()).deepEquals([calendars.get("ownCalendar")!])
})
o("it returns only own calendars for invite", function () {
userController.user = createUser({ _id: "ownerId" })
userController.user = createTestEntity(UserTypeRef, { _id: "ownerId" })
// add it as a writable calendar so that we see that it's filtered out
addCapability(userController.user, "sharedCalendar", ShareCapability.Write)
const model = getOldInviteModel({})
@ -578,12 +596,12 @@ o.spec("CalendarEventWhoModel", function () {
})
o("it returns only existing calendar if it's existing shared event with attendees", function () {
userController.user = createUser({ _id: "ownerId" })
userController.user = createTestEntity(UserTypeRef, { _id: "ownerId" })
// add it as a writable calendar so that we see that it's filtered out
addCapability(userController.user, "sharedCalendar", ShareCapability.Write)
const model = getOldSharedModel(
{
attendees: [createCalendarEventAttendee({ address: otherAddress, status: CalendarAttendeeStatus.NEEDS_ACTION })],
attendees: [createTestEntity(CalendarEventAttendeeTypeRef, { address: otherAddress, status: CalendarAttendeeStatus.NEEDS_ACTION })],
},
EventType.LOCKED,
)
@ -591,7 +609,7 @@ o.spec("CalendarEventWhoModel", function () {
})
o("it returns only the current calendar for single-instance editing", function () {
userController.user = createUser({ _id: "ownerId" })
userController.user = createTestEntity(UserTypeRef, { _id: "ownerId" })
addCapability(userController.user, "sharedCalendar", ShareCapability.Write)
const model = getOldModelWithSingleEdit({ attendees: [] })
o(model.getAvailableCalendars()).deepEquals([calendars.get("ownCalendar")!])
@ -609,21 +627,21 @@ o.spec("CalendarEventWhoModel", function () {
o.spec("invites in own calendar, changing own attendance", function () {
o("changing own attendance on new event results in responseModel and correct status", async function () {
const userController = makeUserController([], AccountType.PAID)
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_ownerGroup: "ownCalendar",
startTime: getDateInZone("2020-06-01"),
endTime: getDateInZone("2020-06-02"),
organizer: otherAddress,
attendees: [
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.DECLINED,
address: otherAddress,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.NEEDS_ACTION,
address: ownerAddress,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.NEEDS_ACTION,
address: otherAddress2,
}),
@ -654,21 +672,21 @@ o.spec("CalendarEventWhoModel", function () {
})
o("changing own attendance on existing event results in responseModel and correct status", async function () {
const userController = makeUserController([], AccountType.PAID)
const existingEvent = createCalendarEvent({
const existingEvent = createTestEntity(CalendarEventTypeRef, {
_ownerGroup: "ownCalendar",
startTime: new Date(2020, 5, 1),
endTime: new Date(2020, 5, 2),
organizer: otherAddress,
attendees: [
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.DECLINED,
address: otherAddress,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.NEEDS_ACTION,
address: ownerAddress,
}),
createCalendarEventAttendee({
createTestEntity(CalendarEventAttendeeTypeRef, {
status: CalendarAttendeeStatus.NEEDS_ACTION,
address: otherAddress2,
}),

View file

@ -3,8 +3,9 @@ import { AccountType, FeatureType } from "../../../../src/api/common/TutanotaCon
import { hasPlanWithInvites } from "../../../../src/calendar/date/eventeditor/CalendarNotificationModel.js"
import { LoginController } from "../../../../src/api/main/LoginController.js"
import { object, replace, when } from "testdouble"
import { createPlanConfiguration, Customer } from "../../../../src/api/entities/sys/TypeRefs.js"
import { Customer, PlanConfigurationTypeRef } from "../../../../src/api/entities/sys/TypeRefs.js"
import { UserController } from "../../../../src/api/main/UserController.js"
import { createTestEntity } from "../../TestUtils.js"
o.spec("CalendarNotificationModel", function () {
let userController: UserController
@ -22,7 +23,7 @@ o.spec("CalendarNotificationModel", function () {
o.spec("hasPlanWithInvites", async function () {
o("available for users with new paid plan that contains invites", async function () {
when(userController.isNewPaidPlan()).thenResolve(true)
when(userController.getPlanConfig()).thenResolve(createPlanConfiguration({ eventInvites: true }))
when(userController.getPlanConfig()).thenResolve(createTestEntity(PlanConfigurationTypeRef, { eventInvites: true }))
replace(userController, "user", { accountType: AccountType.PAID })
replace(customer, "customizations", [])
o(await hasPlanWithInvites(logins)).equals(true)
@ -30,7 +31,7 @@ o.spec("CalendarNotificationModel", function () {
o("not available for users with new paid plan that does not contain invites", async function () {
when(userController.isNewPaidPlan()).thenResolve(true)
when(userController.getPlanConfig()).thenResolve(createPlanConfiguration({ eventInvites: false }))
when(userController.getPlanConfig()).thenResolve(createTestEntity(PlanConfigurationTypeRef, { eventInvites: false }))
replace(userController, "user", { accountType: AccountType.PAID })
o(await hasPlanWithInvites(logins)).equals(false)
})

View file

@ -909,17 +909,17 @@ o.spec("ContactMergeUtilsTest", function () {
o(keptContact.phoneNumbers.length).equals(3)
})
o("getMergedPhoneNumber should ignore whitespace", function () {
const numberWithoutWhitespace = createContactPhoneNumber({
const numberWithoutWhitespace = createTestEntity(ContactPhoneNumberTypeRef, {
number: "789654123",
})
const numberWithWhitespace = createContactPhoneNumber({
const numberWithWhitespace = createTestEntity(ContactPhoneNumberTypeRef, {
number: " 789 654123 ",
})
const mergedPhoneNumbers = _getMergedPhoneNumbers([numberWithoutWhitespace], [numberWithWhitespace])
o(mergedPhoneNumbers).deepEquals([
createContactPhoneNumber({
createTestEntity(ContactPhoneNumberTypeRef, {
number: "789654123",
}),
])

View file

@ -6,8 +6,8 @@ import { matchers, object, verify, when } from "testdouble"
import { FileReference } from "../../../src/api/common/utils/FileUtils.js"
import { neverNull } from "@tutao/tutanota-utils"
import { DataFile } from "../../../src/api/common/DataFile.js"
import { BlobTypeRef, createBlob } from "../../../src/api/entities/sys/TypeRefs.js"
import { createFile } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { BlobTypeRef } from "../../../src/api/entities/sys/TypeRefs.js"
import { FileTypeRef } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { FileControllerNative } from "../../../src/file/FileControllerNative.js"
import { FileControllerBrowser } from "../../../src/file/FileControllerBrowser.js"
import { ConnectionError } from "../../../src/api/common/error/RestError.js"
@ -46,7 +46,7 @@ o.spec("FileControllerTest", function () {
o("should download non-legacy file natively using the blob service", async function () {
const blobs = [createTestEntity(BlobTypeRef)]
const file = createFile({ blobs: blobs, name: "test.txt", mimeType: "plain/text", _id: ["fileListId", "fileElementId"] })
const file = createTestEntity(FileTypeRef, { blobs: blobs, name: "test.txt", mimeType: "plain/text", _id: ["fileListId", "fileElementId"] })
const fileReference = object<FileReference>()
when(blobFacadeMock.downloadAndDecryptNative(anything(), anything(), anything(), anything())).thenResolve(fileReference)
const result = await fileController.downloadAndDecrypt(file)
@ -67,7 +67,7 @@ o.spec("FileControllerTest", function () {
o("immediately no connection", async function () {
const testableFileController = new FileControllerNative(blobFacadeMock, guiDownload, fileAppMock)
const blobs = [createTestEntity(BlobTypeRef)]
const file = createFile({ blobs: blobs, name: "test.txt", mimeType: "plain/text", _id: ["fileListId", "fileElementId"] })
const file = createTestEntity(FileTypeRef, { blobs: blobs, name: "test.txt", mimeType: "plain/text", _id: ["fileListId", "fileElementId"] })
when(blobFacadeMock.downloadAndDecryptNative(anything(), anything(), anything(), anything())).thenReject(new ConnectionError("no connection"))
await assertThrows(ConnectionError, async () => await testableFileController.download(file))
verify(fileAppMock.deleteFile(anything()), { times: 0 }) // mock for cleanup
@ -75,8 +75,18 @@ o.spec("FileControllerTest", function () {
o("connection lost after 1 already downloaded attachment- already downloaded attachments are processed", async function () {
const testableFileController = new FileControllerNative(blobFacadeMock, guiDownload, fileAppMock)
const blobs = [createTestEntity(BlobTypeRef)]
const fileWorks = createFile({ blobs: blobs, name: "works.txt", mimeType: "plain/text", _id: ["fileListId", "fileElementId"] })
const fileNotWorks = createFile({ blobs: blobs, name: "broken.txt", mimeType: "plain/text", _id: ["fileListId", "fileElementId"] })
const fileWorks = createTestEntity(FileTypeRef, {
blobs: blobs,
name: "works.txt",
mimeType: "plain/text",
_id: ["fileListId", "fileElementId"],
})
const fileNotWorks = createTestEntity(FileTypeRef, {
blobs: blobs,
name: "broken.txt",
mimeType: "plain/text",
_id: ["fileListId", "fileElementId"],
})
const fileReferenceWorks: FileReference = {
name: "works.txt",
mimeType: "plain/text",
@ -101,7 +111,7 @@ o.spec("FileControllerTest", function () {
o("should download non-legacy file non-natively using the blob service", async function () {
const blobs = [createTestEntity(BlobTypeRef)]
const file = createFile({ blobs: blobs, name: "test.txt", mimeType: "plain/text", _id: ["fileListId", "fileElementId"] })
const file = createTestEntity(FileTypeRef, { blobs: blobs, name: "test.txt", mimeType: "plain/text", _id: ["fileListId", "fileElementId"] })
const data = new Uint8Array([1, 2, 3])
when(blobFacadeMock.downloadAndDecrypt(anything(), anything())).thenResolve(data)
const result = await fileController.downloadAndDecrypt(file)

View file

@ -1,7 +1,7 @@
import o from "@tutao/otest"
import { DisplayMode, isLegacyDomain, LoginState, LoginViewModel } from "../../../src/login/LoginViewModel.js"
import type { LoginController } from "../../../src/api/main/LoginController.js"
import { createGroupInfo, createUser, UserTypeRef } from "../../../src/api/entities/sys/TypeRefs.js"
import { GroupInfoTypeRef, UserTypeRef } from "../../../src/api/entities/sys/TypeRefs.js"
import type { UserController } from "../../../src/api/main/UserController.js"
import { KeyPermanentlyInvalidatedError } from "../../../src/api/common/error/KeyPermanentlyInvalidatedError.js"
import { CredentialAuthenticationError } from "../../../src/api/common/error/CredentialAuthenticationError.js"
@ -118,7 +118,7 @@ o.spec("LoginViewModelTest", () => {
replace(
userControllerMock,
"userGroupInfo",
createGroupInfo({
createTestEntity(GroupInfoTypeRef, {
mailAddress: "test@example.com",
}),
)

View file

@ -3,12 +3,11 @@ import { UserController } from "../../../src/api/main/UserController.js"
import { reminderCutoffDate, shouldShowUpgradeReminder } from "../../../src/login/PostLoginUtils.js"
import { object, when } from "testdouble"
import {
createCustomer,
createCustomerInfo,
createCustomerProperties,
Customer,
CustomerInfo,
CustomerInfoTypeRef,
CustomerProperties,
CustomerPropertiesTypeRef,
CustomerTypeRef,
} from "../../../src/api/entities/sys/TypeRefs.js"
import { Const } from "../../../src/api/common/TutanotaConstants.js"
@ -25,8 +24,8 @@ o.spec("PostLoginUtils", () => {
o.beforeEach(() => {
userController = object()
customerInfo = createCustomerInfo({})
customerProperties = createCustomerProperties({})
customerInfo = createTestEntity(CustomerInfoTypeRef, {})
customerProperties = createTestEntity(CustomerPropertiesTypeRef, {})
customer = createTestEntity(CustomerTypeRef)
when(userController.loadCustomerInfo()).thenResolve(customerInfo)

View file

@ -1,45 +1,46 @@
import o from "@tutao/otest"
import { knowledgeBaseSearch } from "../../../src/knowledgebase/model/KnowledgeBaseSearchFilter.js"
import type { KnowledgeBaseEntry } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { createKnowledgeBaseEntry } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { createKnowledgeBaseEntryKeyword } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { KnowledgeBaseEntryKeywordTypeRef, KnowledgeBaseEntryTypeRef } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { createTestEntity } from "../TestUtils.js"
o.spec("KnowledgeBaseSearchFilter", function () {
o("finds in title with two filtered keywords", function () {
const knowledgebaseEntry1: KnowledgeBaseEntry = createKnowledgeBaseEntry({
const knowledgebaseEntry1: KnowledgeBaseEntry = createTestEntity(KnowledgeBaseEntryTypeRef, {
title: "User forgot their password",
description:
"When a user is certain that they do not remember their password anymore, " +
"first, ask the user if they tried all passwords that come to mind" +
"if the user completed step 1, ask if they can provide proof that they own the account",
keywords: [
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "password",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "forgotten",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "reset",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "account",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "access",
}),
],
})
const knowledgebaseEntry2: KnowledgeBaseEntry = createKnowledgeBaseEntry({
const knowledgebaseEntry2: KnowledgeBaseEntry = createTestEntity(KnowledgeBaseEntryTypeRef, {
title: "User cannot access account anymore",
description: "A general entry for when the user cannot access their account",
keywords: [
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "access",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "account",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "lost",
}),
],
@ -48,43 +49,43 @@ o.spec("KnowledgeBaseSearchFilter", function () {
o(knowledgeBaseSearch("password", allFakeEntries)).deepEquals([knowledgebaseEntry1]) // should find knowledgebaseEntry1
})
o("finds in title without filtered keywords", function () {
const knowledgebaseEntry1: KnowledgeBaseEntry = createKnowledgeBaseEntry({
const knowledgebaseEntry1: KnowledgeBaseEntry = createTestEntity(KnowledgeBaseEntryTypeRef, {
title: "User forgot their password",
description:
"When a user is certain that they do not remember their password anymore" +
"first, ask the user if they tried all passwords that come to mind" +
"if the user completed step 1, ask if they can provide proof that they own the account",
keywords: [
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "password",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "forgotten",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "reset",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "account",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "access",
}),
],
})
const knowledgebaseEntry2: KnowledgeBaseEntry = createKnowledgeBaseEntry({
const knowledgebaseEntry2: KnowledgeBaseEntry = createTestEntity(KnowledgeBaseEntryTypeRef, {
title: "User cannot access account anymore",
description:
"A general entry for when the user cannot access their account" +
"ask user whether its because of the password or other factors as to why they cannot access their account",
keywords: [
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "access",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "account",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "lost",
}),
],
@ -93,46 +94,46 @@ o.spec("KnowledgeBaseSearchFilter", function () {
o(knowledgeBaseSearch("user", allFakeEntries)).deepEquals([knowledgebaseEntry1, knowledgebaseEntry2]) // should find in both entries
})
o("more than one filter word", function () {
const knowledgebaseEntry1: KnowledgeBaseEntry = createKnowledgeBaseEntry({
const knowledgebaseEntry1: KnowledgeBaseEntry = createTestEntity(KnowledgeBaseEntryTypeRef, {
title: "Payment has been booked but features arent accessible",
description:
"Something went wrong and the payment registered, but the user believes their features arent accessible yet" +
"first, check how long the time between payment and contact has been" +
"if it has been more than X days, ask the user to provide a bill or payment proof",
keywords: [
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "payment",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "features",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "inaccessible",
}),
],
})
const knowledgebaseEntry2: KnowledgeBaseEntry = createKnowledgeBaseEntry({
const knowledgebaseEntry2: KnowledgeBaseEntry = createTestEntity(KnowledgeBaseEntryTypeRef, {
title: "Payment hasn't been booked yet, features aren't accessible either",
description:
"Something went wrong and the payment never registered" +
"ask user if they can provide a bill or payment proof" +
"if provided, re-do the booking and enable the features for the user",
keywords: [
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "payment",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "unregistered",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "inaccessible",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "features",
}),
],
})
const knowledgebaseEntry3: KnowledgeBaseEntry = createKnowledgeBaseEntry({
const knowledgebaseEntry3: KnowledgeBaseEntry = createTestEntity(KnowledgeBaseEntryTypeRef, {
title: "Features don't work as intended, or are buggy",
description:
"The user has reported features that do not work as intended and hinder the users' experience" +
@ -140,16 +141,16 @@ o.spec("KnowledgeBaseSearchFilter", function () {
"if the problem is known, explain that the team is working on a fix, or explain a temporary fix" +
"if its a new problem, tell the user that it has been reported to the team and will be taken care of",
keywords: [
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "functionality",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "not",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "working",
}),
createKnowledgeBaseEntryKeyword({
createTestEntity(KnowledgeBaseEntryKeywordTypeRef, {
keyword: "bug",
}),
],

View file

@ -5,7 +5,7 @@ import { spy } from "@tutao/tutanota-test-utils"
import type { MailboxDetail } from "../../../src/mail/model/MailModel.js"
import { MailModel } from "../../../src/mail/model/MailModel.js"
import { MailFolderType, OperationType } from "../../../src/api/common/TutanotaConstants.js"
import { createMailFolder, MailTypeRef } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { MailFolderTypeRef, MailTypeRef } from "../../../src/api/entities/tutanota/TypeRefs.js"
import type { EntityUpdateData } from "../../../src/api/main/EventController.js"
import { EntityClient } from "../../../src/api/common/EntityClient.js"
import { EntityRestClientMock } from "../api/worker/rest/EntityRestClientMock.js"
@ -18,15 +18,16 @@ import { FolderSystem } from "../../../src/api/common/mail/FolderSystem.js"
import { WebsocketConnectivityModel } from "../../../src/misc/WebsocketConnectivityModel.js"
import { InboxRuleHandler } from "../../../src/mail/model/InboxRuleHandler.js"
import { UserController } from "../../../src/api/main/UserController.js"
import { createTestEntity } from "../TestUtils.js"
o.spec("MailModelTest", function () {
let notifications: Partial<Notifications>
let showSpy: Spy
let model: MailModel
const inboxFolder = createMailFolder({ _id: ["folderListId", "inboxId"] })
const inboxFolder = createTestEntity(MailFolderTypeRef, { _id: ["folderListId", "inboxId"] })
inboxFolder.mails = "instanceListId"
inboxFolder.folderType = MailFolderType.INBOX
const anotherFolder = createMailFolder({ _id: ["folderListId", "archiveId"] })
const anotherFolder = createTestEntity(MailFolderTypeRef, { _id: ["folderListId", "archiveId"] })
anotherFolder.mails = "anotherListId"
anotherFolder.folderType = MailFolderType.ARCHIVE
let mailboxDetails: Partial<MailboxDetail>[]

View file

@ -5,6 +5,7 @@ import type { UserController } from "../../../src/api/main/UserController.js"
import type { LoginController } from "../../../src/api/main/LoginController.js"
import { MailboxDetail, MailModel } from "../../../src/mail/model/MailModel.js"
import {
BodyTypeRef,
Contact,
ContactListTypeRef,
ContactTypeRef,
@ -24,8 +25,10 @@ import {
MailboxGroupRootTypeRef,
MailboxPropertiesTypeRef,
MailBoxTypeRef,
MailDetailsTypeRef,
MailTypeRef,
NotificationMailTypeRef,
TutanotaPropertiesTypeRef,
} from "../../../src/api/entities/tutanota/TypeRefs.js"
import { ContactModel } from "../../../src/contacts/model/ContactModel.js"
import { assertThrows, verify } from "@tutao/tutanota-test-utils"
@ -39,6 +42,8 @@ import {
createGroupMembership,
createUser,
CustomerTypeRef,
GroupInfoTypeRef,
GroupMembershipTypeRef,
GroupTypeRef,
UserTypeRef,
} from "../../../src/api/entities/sys/TypeRefs.js"
@ -134,19 +139,19 @@ o.spec("SendMailModel", function () {
when(mailFacade.getRecipientKeyData(anything())).thenResolve(null)
when(mailFacade.getAttachmentIds(anything())).thenResolve([])
const tutanotaProperties = createTutanotaProperties({
const tutanotaProperties = createTestEntity(TutanotaPropertiesTypeRef, {
defaultSender: DEFAULT_SENDER_FOR_TESTING,
defaultUnconfidential: true,
notificationMailLanguage: "en",
noAutomaticContacts: false,
})
const user = createUser({
userGroup: createGroupMembership({
const user = createTestEntity(UserTypeRef, {
userGroup: createTestEntity(GroupMembershipTypeRef, {
_id: testIdGenerator.newId(),
group: testIdGenerator.newId(),
}),
memberships: [
createGroupMembership({
createTestEntity(GroupMembershipTypeRef, {
_id: testIdGenerator.newId(),
groupType: GroupType.Contact,
}),
@ -167,7 +172,7 @@ o.spec("SendMailModel", function () {
const mailboxDetails: MailboxDetail = {
mailbox: createTestEntity(MailBoxTypeRef),
folders: new FolderSystem([]),
mailGroupInfo: createGroupInfo({
mailGroupInfo: createTestEntity(GroupInfoTypeRef, {
mailAddress: "mailgroup@addre.ss",
}),
mailGroup: createTestEntity(GroupTypeRef),
@ -270,7 +275,7 @@ o.spec("SendMailModel", function () {
o(initializedModel.hasMailChanged()).equals(false)("initialization should not flag mail changed")
})
o("initWithDraft with blank data", async function () {
const draftMail = createMail({
const draftMail = createTestEntity(MailTypeRef, {
confidential: false,
sender: createTestEntity(MailAddressTypeRef),
toRecipients: [],
@ -282,14 +287,14 @@ o.spec("SendMailModel", function () {
})
const mailWrapper = MailWrapper.details(
draftMail,
createMailDetails({
body: createBody({
createTestEntity(MailDetailsTypeRef, {
body: createTestEntity(BodyTypeRef, {
text: BODY_TEXT_1,
}),
}),
)
when(entity.load(ConversationEntryTypeRef, draftMail.conversationEntry)).thenResolve(
createConversationEntry({ conversationType: ConversationType.REPLY }),
createTestEntity(ConversationEntryTypeRef, { conversationType: ConversationType.REPLY }),
)
const initializedModel = await model.initWithDraft([], mailWrapper, new Map())
o(initializedModel.getConversationType()).equals(ConversationType.REPLY)
@ -304,19 +309,19 @@ o.spec("SendMailModel", function () {
o(initializedModel.hasMailChanged()).equals(false)("initialization should not flag mail changed")
})
o("initWithDraft with some data", async function () {
const draftMail = createMail({
const draftMail = createTestEntity(MailTypeRef, {
confidential: true,
sender: createTestEntity(MailAddressTypeRef),
toRecipients: [
createMailAddress({
createTestEntity(MailAddressTypeRef, {
address: "",
}),
createMailAddress({
createTestEntity(MailAddressTypeRef, {
address: EXTERNAL_ADDRESS_1,
}),
],
ccRecipients: [
createMailAddress({
createTestEntity(MailAddressTypeRef, {
address: EXTERNAL_ADDRESS_2,
}),
],
@ -325,10 +330,13 @@ o.spec("SendMailModel", function () {
replyTos: [],
conversationEntry: testIdGenerator.newIdTuple(),
})
const mailWrapper = MailWrapper.details(draftMail, createMailDetails({ body: createBody({ text: BODY_TEXT_1 }) }))
const mailWrapper = MailWrapper.details(
draftMail,
createTestEntity(MailDetailsTypeRef, { body: createTestEntity(BodyTypeRef, { text: BODY_TEXT_1 }) }),
)
when(entity.load(ConversationEntryTypeRef, draftMail.conversationEntry)).thenResolve(
createConversationEntry({ conversationType: ConversationType.FORWARD }),
createTestEntity(ConversationEntryTypeRef, { conversationType: ConversationType.FORWARD }),
)
const initializedModel = await model.initWithDraft([], mailWrapper, new Map())
@ -539,7 +547,7 @@ o.spec("SendMailModel", function () {
o("when a recipient has an existing contact, and the saved password changes, then the contact will be updated", async function () {
const getConfirmation = func<(TranslationKey) => Promise<boolean>>()
const contact = createContact({
const contact = createTestEntity(ContactTypeRef, {
_id: testIdGenerator.newIdTuple(),
firstName: "my",
lastName: "chippie",
@ -563,7 +571,7 @@ o.spec("SendMailModel", function () {
let existingContact
let recipients
o.before(function () {
existingContact = createContact({
existingContact = createTestEntity(ContactTypeRef, {
_id: testIdGenerator.newIdTuple(),
firstName: "james",
lastName: "hetfield",
@ -600,10 +608,10 @@ o.spec("SendMailModel", function () {
firstName: "newfirstname",
lastName: "newlastname",
mailAddresses: [
createMailAddress({
createTestEntity(MailAddressTypeRef, {
address: "james@tuta.com",
}),
createMailAddress({
createTestEntity(MailAddressTypeRef, {
address: "address2@hotmail.com",
}),
],
@ -633,7 +641,7 @@ o.spec("SendMailModel", function () {
firstName: "james",
lastName: "hetfield",
mailAddresses: [
createMailAddress({
createTestEntity(MailAddressTypeRef, {
address: "nolongerjames@hotmail.com",
}),
],

View file

@ -1,46 +1,52 @@
import o from "@tutao/otest"
import type { EmailTemplate } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { createEmailTemplate, createEmailTemplateContent } from "../../../src/api/entities/tutanota/TypeRefs.js"
import {
createEmailTemplate,
createEmailTemplateContent,
EmailTemplateContentTypeRef,
EmailTemplateTypeRef,
} from "../../../src/api/entities/tutanota/TypeRefs.js"
import { searchInTemplates } from "../../../src/templates/model/TemplatePopupModel.js"
import { createTestEntity } from "../TestUtils.js"
o.spec("TemplateSearchFilter", function () {
const abcTemplate = createEmailTemplate({
const abcTemplate = createTestEntity(EmailTemplateTypeRef, {
tag: "aBc_tag",
title: "aBc_title",
contents: [
createEmailTemplateContent({
createTestEntity(EmailTemplateContentTypeRef, {
languageCode: "en",
text: "aBc english",
}),
createEmailTemplateContent({
createTestEntity(EmailTemplateContentTypeRef, {
languageCode: "de",
text: "aBc deutsch",
}),
],
})
const defTemplate = createEmailTemplate({
const defTemplate = createTestEntity(EmailTemplateTypeRef, {
tag: "dEf_tag",
title: "dEf_title",
contents: [
createEmailTemplateContent({
createTestEntity(EmailTemplateContentTypeRef, {
languageCode: "en",
text: "dEf english",
}),
createEmailTemplateContent({
createTestEntity(EmailTemplateContentTypeRef, {
languageCode: "de",
text: "dEf deutsch",
}),
],
})
const abcdefTemplate = createEmailTemplate({
const abcdefTemplate = createTestEntity(EmailTemplateTypeRef, {
tag: "abcdef_tag",
title: "abcdef_title",
contents: [
createEmailTemplateContent({
createTestEntity(EmailTemplateContentTypeRef, {
languageCode: "en",
text: "abcdef english",
}),
createEmailTemplateContent({
createTestEntity(EmailTemplateContentTypeRef, {
languageCode: "de",
text: "abcdef deutsch",
}),

View file

@ -5,8 +5,10 @@ import {
createMail,
createMailAddress,
FileTypeRef,
MailAddressTypeRef,
MailBodyTypeRef,
MailHeadersTypeRef,
MailTypeRef,
} from "../../../../src/api/entities/tutanota/TypeRefs.js"
import { MailState } from "../../../../src/api/common/TutanotaConstants.js"
import { DataFile } from "../../../../src/api/common/DataFile.js"
@ -15,6 +17,7 @@ import { EntityClient } from "../../../../src/api/common/EntityClient.js"
import { FileController } from "../../../../src/file/FileController.js"
import { object, when } from "testdouble"
import { MailFacade } from "../../../../src/api/worker/facades/lazy/MailFacade.js"
import { createTestEntity } from "../../TestUtils.js"
o.spec("Bundler", function () {
let entityClientMock: EntityClient
@ -43,8 +46,8 @@ o.spec("Bundler", function () {
const receivedOn = new Date()
const headers = "this is the headers"
const mailHeadersId = "mailheadersid"
const attachmentListId = "attachmentListId"
const attachmentIds = ["attachmentId1", "attachmentId2", "attachmentId3"]
const attachmentListId: Id = "attachmentListId"
const attachmentIds: Id[] = ["attachmentId1", "attachmentId2", "attachmentId3"]
const attachments: Array<DataFile> = attachmentIds.map((id) => {
return {
_type: "DataFile",
@ -56,11 +59,11 @@ o.spec("Bundler", function () {
mimeType: "test",
}
})
const mail = createMail({
const mail = createTestEntity(MailTypeRef, {
_id: mailId,
body: mailBodyId,
subject,
sender: createMailAddress(sender),
sender: createTestEntity(MailAddressTypeRef, sender),
toRecipients: to.map(createMailAddress),
ccRecipients: cc.map(createMailAddress),
bccRecipients: bcc.map(createMailAddress),
@ -70,7 +73,7 @@ o.spec("Bundler", function () {
receivedDate: receivedOn,
sentDate: sentOn,
headers: mailHeadersId,
attachments: attachmentIds.map((id) => [attachmentListId, id]),
attachments: attachmentIds.map((id) => [attachmentListId, id] as IdTuple),
})
when(entityClientMock.load(MailHeadersTypeRef, mailHeadersId)).thenResolve({ headers })

View file

@ -1,31 +1,32 @@
import o from "@tutao/otest"
import { createMailFolder } from "../../../../src/api/entities/tutanota/TypeRefs.js"
import { createMailFolder, MailFolderTypeRef } from "../../../../src/api/entities/tutanota/TypeRefs.js"
import { MailFolderType } from "../../../../src/api/common/TutanotaConstants.js"
import { FolderSystem } from "../../../../src/api/common/mail/FolderSystem.js"
import { createTestEntity } from "../../TestUtils.js"
o.spec("FolderSystem", function () {
const listId = "listId"
const inbox = createMailFolder({ _id: [listId, "inbox"], folderType: MailFolderType.INBOX })
const archive = createMailFolder({ _id: [listId, "archive"], folderType: MailFolderType.ARCHIVE })
const customFolder = createMailFolder({
const inbox = createTestEntity(MailFolderTypeRef, { _id: [listId, "inbox"], folderType: MailFolderType.INBOX })
const archive = createTestEntity(MailFolderTypeRef, { _id: [listId, "archive"], folderType: MailFolderType.ARCHIVE })
const customFolder = createTestEntity(MailFolderTypeRef, {
_id: [listId, "custom"],
folderType: MailFolderType.CUSTOM,
name: "X",
})
const customSubfolder = createMailFolder({
const customSubfolder = createTestEntity(MailFolderTypeRef, {
_id: [listId, "customSub"],
folderType: MailFolderType.CUSTOM,
parentFolder: customFolder._id,
name: "AA",
mails: "customSubMailList",
})
const customSubSubfolder = createMailFolder({
const customSubSubfolder = createTestEntity(MailFolderTypeRef, {
_id: [listId, "customSubSub"],
folderType: MailFolderType.CUSTOM,
parentFolder: customSubfolder._id,
name: "B",
})
const customSubSubfolderAnother = createMailFolder({
const customSubSubfolderAnother = createTestEntity(MailFolderTypeRef, {
_id: [listId, "customSubSubAnother"],
folderType: MailFolderType.CUSTOM,
parentFolder: customSubfolder._id,
@ -71,12 +72,12 @@ o.spec("FolderSystem", function () {
})
o("indented list sorts stepsiblings correctly", function () {
const customFolderAnother = createMailFolder({
const customFolderAnother = createTestEntity(MailFolderTypeRef, {
_id: [listId, "customAnother"],
folderType: MailFolderType.CUSTOM,
name: "Another top-level custom",
})
const customFolderAnotherSub = createMailFolder({
const customFolderAnotherSub = createTestEntity(MailFolderTypeRef, {
_id: [listId, "customAnotherSub"],
folderType: MailFolderType.CUSTOM,
parentFolder: customFolderAnother._id,

View file

@ -2,6 +2,7 @@ import o from "@tutao/otest"
import { ConversationItem, ConversationPrefProvider, ConversationViewModel } from "../../../../src/mail/view/ConversationViewModel.js"
import {
ConversationEntry,
ConversationEntryTypeRef,
createConversationEntry,
createMail,
createMailboxProperties,
@ -9,6 +10,8 @@ import {
Mail,
MailboxProperties,
MailboxPropertiesTypeRef,
MailFolderTypeRef,
MailTypeRef,
} from "../../../../src/api/entities/tutanota/TypeRefs.js"
import { ownerId } from "../../calendar/CalendarTestUtils.js"
import { CreateMailViewerOptions } from "../../../../src/mail/view/MailViewer.js"
@ -82,12 +85,12 @@ o.spec("ConversationViewModel", function () {
const addMail = (mailId: string): Mail => {
const conversationId = "conversation" + mailId
const newMail = createMail({
const newMail = createTestEntity(MailTypeRef, {
_id: [listId, mailId],
conversationEntry: [listId, conversationId],
state: MailState.RECEIVED,
})
const mailConversationEntry = createConversationEntry({
const mailConversationEntry = createTestEntity(ConversationEntryTypeRef, {
_id: [listId, conversationId],
mail: newMail._id,
previous: primaryMail?._id,
@ -175,7 +178,7 @@ o.spec("ConversationViewModel", function () {
const trashDraftMail = addMail("trashDraftMail")
trashDraftMail.state = MailState.DRAFT
const trash = createMailFolder({ _id: [listId, "trashFolder"], folderType: MailFolderType.TRASH })
const trash = createTestEntity(MailFolderTypeRef, { _id: [listId, "trashFolder"], folderType: MailFolderType.TRASH })
entityRestClientMock.addListInstances(trash)
when(mailModel.getMailboxDetailsForMail(matchers.anything())).thenResolve(mailboxDetail)
@ -197,7 +200,7 @@ o.spec("ConversationViewModel", function () {
const trashDraftMail = addMail("trashDraftMail")
trashDraftMail.state = MailState.DRAFT
const trash = createMailFolder({ _id: [listId, "trashFolder"], folderType: MailFolderType.TRASH })
const trash = createTestEntity(MailFolderTypeRef, { _id: [listId, "trashFolder"], folderType: MailFolderType.TRASH })
entityRestClientMock.addListInstances(trash)
when(mailModel.getMailboxDetailsForMail(trashDraftMail)).thenResolve(mailboxDetail)
@ -248,13 +251,13 @@ o.spec("ConversationViewModel", function () {
await loadingDefer.promise
conversation.pop() // "deleting" the mail
const mailConversationEntry = createConversationEntry({
const mailConversationEntry = createTestEntity(ConversationEntryTypeRef, {
_id: anotherMail.conversationEntry,
mail: anotherMail._id,
previous: primaryMail?._id,
})
await entityRestClientMock.erase(mailConversationEntry)
const deletedmailConversationEntry = createConversationEntry({
const deletedmailConversationEntry = createTestEntity(ConversationEntryTypeRef, {
_id: anotherMail.conversationEntry,
previous: primaryMail?._id,
})
@ -313,7 +316,7 @@ o.spec("ConversationViewModel", function () {
await loadingDefer.promise
conversation.pop()
const trash = createMailFolder({ _id: ["newListId", "trashFolder"], folderType: MailFolderType.TRASH })
const trash = createTestEntity(MailFolderTypeRef, { _id: ["newListId", "trashFolder"], folderType: MailFolderType.TRASH })
entityRestClientMock.addListInstances(trash)
// adding new mail (is the same mail, just moved to trash)
const newTrashDraftMail = addMail("trashDraftMail")

View file

@ -2,11 +2,12 @@ import o from "@tutao/otest"
import { ListModel, ListModelConfig } from "../../../src/misc/ListModel.js"
import { GENERATED_MAX_ID, getElementId, sortCompareById, timestampToGeneratedId } from "../../../src/api/common/utils/EntityUtils.js"
import { defer, DeferredObject } from "@tutao/tutanota-utils"
import { createKnowledgeBaseEntry, KnowledgeBaseEntry } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { createKnowledgeBaseEntry, KnowledgeBaseEntry, KnowledgeBaseEntryTypeRef } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { ListFetchResult } from "../../../src/gui/base/ListUtils.js"
import { ListLoadingState } from "../../../src/gui/base/List.js"
import { ConnectionError } from "../../../src/api/common/error/RestError.js"
import { OperationType } from "../../../src/api/common/TutanotaConstants.js"
import { createTestEntity } from "../TestUtils.js"
o.spec("ListModel", function () {
const listId = "listId"
@ -21,19 +22,19 @@ o.spec("ListModel", function () {
},
}
const itemA = createKnowledgeBaseEntry({
const itemA = createTestEntity(KnowledgeBaseEntryTypeRef, {
_id: [listId, "a"],
title: "a",
})
const itemB = createKnowledgeBaseEntry({
const itemB = createTestEntity(KnowledgeBaseEntryTypeRef, {
_id: [listId, "b"],
title: "b",
})
const itemC = createKnowledgeBaseEntry({
const itemC = createTestEntity(KnowledgeBaseEntryTypeRef, {
_id: [listId, "c"],
title: "c",
})
const itemD = createKnowledgeBaseEntry({
const itemD = createTestEntity(KnowledgeBaseEntryTypeRef, {
_id: [listId, "d"],
title: "d",
})
@ -84,7 +85,7 @@ o.spec("ListModel", function () {
const moreLoading = listModel.loadMore()
o(listModel.state.loadingStatus).equals(ListLoadingState.Loading)
const knowledgeBaseEntry = createKnowledgeBaseEntry({
const knowledgeBaseEntry = createTestEntity(KnowledgeBaseEntryTypeRef, {
_id: [listId, timestampToGeneratedId(10)],
})
fetchDefer.resolve({
@ -736,7 +737,7 @@ o.spec("ListModel", function () {
o.spec("Updating items", function () {
o("update for item with id sorting updates item", async function () {
const updatedItemD = createKnowledgeBaseEntry({ ...itemD, title: "AA" })
const updatedItemD = createTestEntity(KnowledgeBaseEntryTypeRef, { ...itemD, title: "AA" })
const newConfig: ListModelConfig<KnowledgeBaseEntry> = {
...defaultListConfig,
@ -758,7 +759,7 @@ o.spec("ListModel", function () {
})
o("update for item with custom sorting changes position", async function () {
const updatedItemD = createKnowledgeBaseEntry({ ...itemD, title: "AA" })
const updatedItemD = createTestEntity(KnowledgeBaseEntryTypeRef, { ...itemD, title: "AA" })
const newConfig: ListModelConfig<KnowledgeBaseEntry> = {
...defaultListConfig,

View file

@ -3,9 +3,10 @@ import { IServiceExecutor } from "../../../src/api/common/ServiceRequest.js"
import { object, verify, when } from "testdouble"
import { NewsItemStorage, NewsModel } from "../../../src/misc/news/NewsModel.js"
import { NewsService } from "../../../src/api/entities/tutanota/Services.js"
import { createNewsId, createNewsIn, createNewsOut, NewsId } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { createNewsId, createNewsIn, createNewsOut, NewsId, NewsIdTypeRef, NewsInTypeRef, NewsOutTypeRef } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { NewsListItem } from "../../../src/misc/news/NewsListItem.js"
import { Children } from "mithril"
import { createTestEntity } from "../TestUtils.js"
o.spec("NewsModel", function () {
let newsModel: NewsModel
@ -30,14 +31,14 @@ o.spec("NewsModel", function () {
newsModel = new NewsModel(serviceExecutor, storage, async () => new DummyNews())
newsIds = [
createNewsId({
createTestEntity(NewsIdTypeRef, {
newsItemId: "ID:dummyNews",
newsItemName: "dummyNews",
}),
]
when(serviceExecutor.get(NewsService, null)).thenResolve(
createNewsOut({
createTestEntity(NewsOutTypeRef, {
newsItemIds: newsIds,
}),
)
@ -56,7 +57,8 @@ o.spec("NewsModel", function () {
await newsModel.acknowledgeNews(newsIds[0].newsItemId)
verify(serviceExecutor.post(NewsService, createNewsIn({ newsItemId: newsIds[0].newsItemId })))
const expectedNewsIn = createTestEntity(NewsInTypeRef, { newsItemId: newsIds[0].newsItemId })
verify(serviceExecutor.post(NewsService, expectedNewsIn))
})
})
})

View file

@ -1,9 +1,10 @@
import o from "@tutao/otest"
import { createOutOfOfficeNotification } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { OutOfOfficeNotificationTypeRef } from "../../../src/api/entities/tutanota/TypeRefs.js"
import { mockAttribute, unmockAttribute } from "@tutao/tutanota-test-utils"
import { getDayShifted, getStartOfDay, getStartOfNextDay } from "@tutao/tutanota-utils"
import { lang } from "../../../src/misc/LanguageViewModel.js"
import { formatActivateState, isNotificationCurrentlyActive } from "../../../src/misc/OutOfOfficeNotificationUtils.js"
import { createTestEntity } from "../TestUtils.js"
o.spec("OutOfOfficeNotificationTest", function () {
const mockedAttributes: any = []
@ -28,26 +29,26 @@ o.spec("OutOfOfficeNotificationTest", function () {
o("Active state formatting", function () {
lang._setLanguageTag("en")
let notification = createOutOfOfficeNotification({
let notification = createTestEntity(OutOfOfficeNotificationTypeRef, {
enabled: true,
startDate: null,
endDate: null,
})
o(formatActivateState(notification)).equals("Activated")
notification = createOutOfOfficeNotification({
notification = createTestEntity(OutOfOfficeNotificationTypeRef, {
enabled: true,
startDate: new Date(2020, 11, 15),
endDate: null,
})
o(formatActivateState(notification)).equals("Activated (12/15/2020)")
notification = createOutOfOfficeNotification({
notification = createTestEntity(OutOfOfficeNotificationTypeRef, {
enabled: true,
startDate: new Date(2020, 11, 15),
endDate: new Date(2021, 0, 9),
})
o(formatActivateState(notification)).equals("Activated (12/15/2020 - 1/8/2021)") // end date should be shifted
notification = createOutOfOfficeNotification({
notification = createTestEntity(OutOfOfficeNotificationTypeRef, {
enabled: false,
startDate: new Date(2020, 11, 15),
endDate: new Date(2021, 0, 10),
@ -58,7 +59,7 @@ o.spec("OutOfOfficeNotificationTest", function () {
const now = new Date()
const oneDayBefore = getDayShifted(now, -1)
const oneDayAfter = getDayShifted(now, +1)
let notification = createOutOfOfficeNotification({
let notification = createTestEntity(OutOfOfficeNotificationTypeRef, {
enabled: true,
startDate: null,
endDate: null,
@ -71,7 +72,7 @@ o.spec("OutOfOfficeNotificationTest", function () {
const now = new Date()
const oneDayBefore = getDayShifted(now, -1)
const oneDayAfter = getDayShifted(now, +1)
let notification = createOutOfOfficeNotification({
let notification = createTestEntity(OutOfOfficeNotificationTypeRef, {
enabled: false,
startDate: null,
endDate: null,
@ -84,7 +85,7 @@ o.spec("OutOfOfficeNotificationTest", function () {
const now = new Date()
const oneDayBefore = getDayShifted(now, -1)
const oneDayAfter = getDayShifted(now, +1)
let notification = createOutOfOfficeNotification({
let notification = createTestEntity(OutOfOfficeNotificationTypeRef, {
enabled: true,
startDate: getStartOfDay(now),
endDate: null,
@ -97,7 +98,7 @@ o.spec("OutOfOfficeNotificationTest", function () {
const now = new Date()
const oneDayBefore = getDayShifted(now, -1)
const oneDayAfter = getDayShifted(now, +1)
let notification = createOutOfOfficeNotification({
let notification = createTestEntity(OutOfOfficeNotificationTypeRef, {
enabled: true,
startDate: getStartOfDay(now),
endDate: getStartOfNextDay(now),
@ -110,7 +111,7 @@ o.spec("OutOfOfficeNotificationTest", function () {
const now = new Date()
const activeUntil = getDayShifted(now, +5)
const oneDayAfter = getStartOfNextDay(activeUntil)
let notification = createOutOfOfficeNotification({
let notification = createTestEntity(OutOfOfficeNotificationTypeRef, {
enabled: true,
startDate: getStartOfDay(now),
endDate: getStartOfNextDay(activeUntil),

Some files were not shown because too many files have changed in this diff Show more