1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-1650 Templates | Default template for new object creation (#462)

This commit is contained in:
Konstantin Ivanov 2023-10-25 10:00:59 +02:00 committed by GitHub
parent 9e43f5af02
commit ad9bc52e2e
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 367 additions and 284 deletions

View file

@ -254,9 +254,6 @@ open class EditorTestSetup {
@Mock
lateinit var threadStatusChannel: ThreadStatusChannel
@Mock
lateinit var documentEmojiIconProvider: DocumentEmojiIconProvider
@Mock
lateinit var createTable: CreateTable
@ -329,8 +326,6 @@ open class EditorTestSetup {
setObjectType = SetObjectType(repo)
createObjectAsMentionOrLink = CreateObjectAsMentionOrLink(
repo = repo,
getDefaultPageType = getDefaultPageType,
getTemplates = getTemplates,
dispatchers = dispatchers,
spaceManager = spaceManager
)

View file

@ -735,8 +735,6 @@ object EditorUseCaseModule {
spaceManager: SpaceManager
): CreateObjectAsMentionOrLink = CreateObjectAsMentionOrLink(
repo = repo,
getDefaultPageType = getDefaultPageType,
getTemplates = getTemplates,
dispatchers = dispatchers,
spaceManager = spaceManager
)

View file

@ -173,7 +173,8 @@ sealed class Command {
val position: Position,
val template: Id?,
val prefilled: Struct,
val internalFlags: List<InternalFlags>
val internalFlags: List<InternalFlags>,
val space: Id
)
/**
@ -187,7 +188,7 @@ sealed class Command {
val template: Id?,
val internalFlags: List<InternalFlags>,
val space: SpaceId,
val type: TypeKey
val typeKey: TypeKey
)
class Move(

View file

@ -4,6 +4,7 @@ import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVFilterCondition
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.RelationFormat
@ -36,9 +37,9 @@ class CreateDataViewObject @Inject constructor(
prefilled = resolveSetByTypePrefilledObjectData(
filters = params.filters
),
internalFlags = listOf(),
internalFlags = listOf(InternalFlags.ShouldSelectTemplate),
space = space,
type = params.type
typeKey = params.type
)
val result = repo.createObject(command)
Result(
@ -54,9 +55,9 @@ class CreateDataViewObject @Inject constructor(
filters = params.filters,
relations = params.relations
),
internalFlags = listOf(),
internalFlags = listOf(InternalFlags.ShouldSelectTemplate),
space = space,
type = params.type
typeKey = params.type
)
val result = repo.createObject(command)
Result(
@ -72,9 +73,9 @@ class CreateDataViewObject @Inject constructor(
filters = emptyList(),
relations = emptyList()
),
internalFlags = listOf(),
internalFlags = listOf(InternalFlags.ShouldSelectTemplate),
space = space,
type = params.type
typeKey = params.type
)
val result = repo.createObject(command)
Result(

View file

@ -2,6 +2,7 @@ package com.anytypeio.anytype.domain.launch
import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVFilterCondition
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.NO_VALUE
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectTypeUniqueKeys
@ -37,12 +38,13 @@ class GetDefaultPageType @Inject constructor(
return if (item != null) {
val key = item.uniqueKey?.let {
TypeKey(it)
}
} ?: TypeKey(ObjectTypeUniqueKeys.NOTE)
val id = TypeId(item.id)
Response(
type = key,
name = item.name,
id = id
id = id,
defaultTemplate = item.defaultTemplateId
)
} else {
fetchDefaultType()
@ -84,25 +86,23 @@ class GetDefaultPageType @Inject constructor(
Relations.ID,
Relations.NAME,
Relations.UNIQUE_KEY,
Relations.SPACE_ID
Relations.SPACE_ID,
Relations.DEFAULT_TEMPLATE_ID
)
)
val note = if (items.isNotEmpty()) {
ObjectWrapper.Type(items.first())
if (items.isNotEmpty()) {
val note = ObjectWrapper.Type(items.first())
val key = TypeKey(note.uniqueKey ?: throw IllegalStateException("Default type has empty key"))
val id = TypeId(note.id)
return Response(
type = key,
name = note.name,
id = id,
defaultTemplate = note.defaultTemplateId
)
} else {
null
throw IllegalStateException("Default type not found")
}
val key = note?.uniqueKey?.let {
TypeKey(it)
}
val id = note?.id?.let {
TypeId(it)
}
return Response(
type = key,
name = note?.name,
id = id
)
}
private suspend fun searchObjectByIdAndSpaceId(
@ -128,7 +128,8 @@ class GetDefaultPageType @Inject constructor(
Relations.ID,
Relations.NAME,
Relations.UNIQUE_KEY,
Relations.SPACE_ID
Relations.SPACE_ID,
Relations.DEFAULT_TEMPLATE_ID
)
)
return if (items.isNotEmpty()) {
@ -166,9 +167,10 @@ class GetDefaultPageType @Inject constructor(
)
)
class Response(
val id: TypeId?,
val type: TypeKey?,
val name: String?
data class Response(
val id: TypeId,
val type: TypeKey,
val name: String?,
val defaultTemplate: Id?
)
}

View file

@ -20,18 +20,15 @@ class CreateBlockLinkWithObject(
override suspend fun doWork(params: Params): Result {
val template = getTemplates.run(
GetTemplates.Params(params.typeId)
).firstOrNull()?.id
val command = Command.CreateBlockLinkWithObject(
context = params.context,
target = params.target,
position = params.position,
prefilled = emptyMap(),
template = template,
internalFlags = listOf(),
type = params.typeKey
template = params.template,
internalFlags = listOf(InternalFlags.ShouldSelectTemplate),
type = params.typeKey,
space = params.space
)
val result = repo.createBlockLinkWithObject(command)
@ -55,7 +52,9 @@ class CreateBlockLinkWithObject(
val target: Id,
val position: Position,
val typeId: TypeId,
val typeKey: TypeKey
val typeKey: TypeKey,
val template: Id?,
val space: Id
)
/**

View file

@ -4,6 +4,7 @@ import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Struct
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
@ -24,23 +25,39 @@ class CreateObject @Inject constructor(
) : ResultInteractor<CreateObject.Param, CreateObject.Result>(dispatchers.io) {
override suspend fun doWork(params: Param): Result {
val type = params.type ?: getDefaultPageType.run(Unit).type
requireNotNull(type) { "Type is undefined" }
val internalFlags = buildList {
add(InternalFlags.ShouldSelectType)
add(InternalFlags.ShouldSelectTemplate)
add(InternalFlags.ShouldEmptyDelete)
if (params.type == null) {
val defType = getDefaultPageType.run(Unit)
return createObject(
typeKey = defType.type,
template = defType.defaultTemplate,
internalFlags = params.internalFlags,
prefilled = emptyMap()
)
} else {
return createObject(
typeKey = params.type,
template = params.template,
internalFlags = params.internalFlags,
prefilled = params.prefilled
)
}
}
private suspend fun createObject(
typeKey: TypeKey,
template: Id?,
internalFlags: List<InternalFlags>,
prefilled: Struct
): Result {
val spaceId = SpaceId(spaceManager.get())
val command = Command.CreateObject(
template = params.template,
prefilled = emptyMap(),
space = spaceId,
typeKey = typeKey,
template = template,
prefilled = prefilled,
internalFlags = internalFlags,
space = SpaceId(spaceManager.get()),
type = type
)
val result = repo.createObject(command)
@ -48,20 +65,22 @@ class CreateObject @Inject constructor(
return Result(
objectId = result.id,
event = result.event,
appliedTemplate = null,
type = type
appliedTemplate = template,
typeKey = typeKey
)
}
data class Param(
val type: TypeKey? = null,
val template: Id? = null
val template: Id? = null,
val internalFlags: List<InternalFlags> = emptyList(),
val prefilled: Struct = emptyMap()
)
data class Result(
val objectId: Id,
val event: Payload,
val appliedTemplate: String? = null,
val type: TypeKey
val typeKey: TypeKey
)
}

View file

@ -1,15 +1,13 @@
package com.anytypeio.anytype.domain.page
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_models.primitives.TypeId
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.ResultInteractor
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.workspace.SpaceManager
/**
@ -18,8 +16,6 @@ import com.anytypeio.anytype.domain.workspace.SpaceManager
class CreateObjectAsMentionOrLink(
private val repo: BlockRepository,
private val getDefaultPageType: GetDefaultPageType,
private val getTemplates: GetTemplates,
private val spaceManager: SpaceManager,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<CreateObjectAsMentionOrLink.Params, CreateObjectAsMentionOrLink.Result>(
@ -30,27 +26,18 @@ class CreateObjectAsMentionOrLink(
val space = SpaceId(spaceManager.get())
val typeKey = params.typeKey ?: getDefaultPageType.run(Unit).type
val typeId = params.typeId ?: getDefaultPageType.run(Unit).id
requireNotNull(typeKey) { "Undefined object type" }
val typeKey = params.typeKey
val prefilled = buildMap {
put(Relations.NAME, params.name)
}
val template = if (typeId != null) {
getTemplates.run(GetTemplates.Params(type = typeId)).firstOrNull()?.id
} else {
null
}
val command = Command.CreateObject(
template = template,
template = params.defaultTemplate,
prefilled = prefilled,
internalFlags = listOf(),
internalFlags = listOf(InternalFlags.ShouldSelectTemplate, InternalFlags.ShouldSelectType),
space = space,
type = typeKey
typeKey = typeKey
)
val result = repo.createObject(command)
@ -66,8 +53,8 @@ class CreateObjectAsMentionOrLink(
*/
data class Params(
val name: String,
val typeKey: TypeKey? = null,
val typeId: TypeId? = null
val typeKey: TypeKey,
val defaultTemplate: String? = null
)
data class Result(

View file

@ -27,7 +27,7 @@ class CreateTemplate @Inject constructor(
internalFlags = emptyList(),
space = SpaceId(spaceManager.get()),
//todo After Space Merge, check this condition!!!
type = TypeKey(ObjectTypeUniqueKeys.TEMPLATE)
typeKey = TypeKey(ObjectTypeUniqueKeys.TEMPLATE)
)
val result = repo.createObject(command)
return result.id

View file

@ -3,6 +3,7 @@ package com.anytypeio.anytype.domain.page
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.CoroutineTestRule
import com.anytypeio.anytype.core_models.CreateBlockLinkWithObjectResult
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Position
@ -54,6 +55,7 @@ class CreateBlockLinkWithObjectTest {
//SETUP
val context = MockDataFactory.randomString()
val target = MockDataFactory.randomString()
val spaceId = MockDataFactory.randomUuid()
val position = Position.LEFT
val typeId = MockDataFactory.randomString()
val type = MockDataFactory.randomString()
@ -66,7 +68,9 @@ class CreateBlockLinkWithObjectTest {
target = target,
position = position,
typeKey = TypeKey(type),
typeId = TypeId(typeId)
typeId = TypeId(typeId),
space = spaceId,
template = null
)
createBlockLinkWithObject.run(params)
@ -77,8 +81,9 @@ class CreateBlockLinkWithObjectTest {
position = position,
prefilled = emptyMap(),
template = null,
internalFlags = listOf(),
type = TypeKey(type)
internalFlags = listOf(InternalFlags.ShouldSelectTemplate),
type = TypeKey(type),
space = spaceId
)
verifyBlocking(repo, times(1)) { createBlockLinkWithObject(commands) }
}
@ -90,13 +95,11 @@ class CreateBlockLinkWithObjectTest {
val context = MockDataFactory.randomString()
val target = MockDataFactory.randomString()
val position = Position.LEFT
val spaceId = MockDataFactory.randomUuid()
val type = MockDataFactory.randomString()
val typeId = MockDataFactory.randomString()
val template = MockDataFactory.randomString()
stubCreateBlockLinkWithObject()
givenGetTemplates(listOf(ObjectWrapper.Basic(buildMap {
put(Relations.ID, template)
})))
//TESTING
val params = CreateBlockLinkWithObject.Params(
@ -104,7 +107,9 @@ class CreateBlockLinkWithObjectTest {
target = target,
position = position,
typeKey = TypeKey(type),
typeId = TypeId(typeId)
typeId = TypeId(typeId),
space = spaceId,
template = template
)
createBlockLinkWithObject.run(params)
@ -115,8 +120,9 @@ class CreateBlockLinkWithObjectTest {
position = position,
prefilled = emptyMap(),
template = template,
internalFlags = listOf(),
type = TypeKey(type)
internalFlags = listOf(InternalFlags.ShouldSelectTemplate),
type = TypeKey(type),
space = spaceId
)
verifyBlocking(repo, times(1)) { createBlockLinkWithObject(commands) }
}
@ -128,21 +134,11 @@ class CreateBlockLinkWithObjectTest {
val context = MockDataFactory.randomString()
val target = MockDataFactory.randomString()
val position = Position.LEFT
val spaceId = MockDataFactory.randomUuid()
val type = MockDataFactory.randomString()
val typeId = MockDataFactory.randomString()
val templateOne = MockDataFactory.randomString()
val templateTwo = MockDataFactory.randomString()
stubCreateBlockLinkWithObject()
givenGetTemplates(
listOf(
ObjectWrapper.Basic(buildMap {
put(Relations.ID, templateOne)
}),
ObjectWrapper.Basic(buildMap {
put(Relations.ID, templateTwo)
})
)
)
//TESTING
val params = CreateBlockLinkWithObject.Params(
@ -150,7 +146,9 @@ class CreateBlockLinkWithObjectTest {
target = target,
position = position,
typeKey = TypeKey(type),
typeId = TypeId(typeId)
typeId = TypeId(typeId),
space = spaceId,
template = templateOne
)
createBlockLinkWithObject.run(params)
@ -160,9 +158,10 @@ class CreateBlockLinkWithObjectTest {
target = target,
position = position,
template = templateOne,
internalFlags = listOf(),
internalFlags = listOf(InternalFlags.ShouldSelectTemplate),
type = TypeKey(type),
prefilled = emptyMap()
prefilled = emptyMap(),
space = spaceId
)
verifyBlocking(repo, times(1)) { createBlockLinkWithObject(commands) }
}

View file

@ -3,6 +3,7 @@ package com.anytypeio.anytype.domain.page
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.CoroutineTestRule
import com.anytypeio.anytype.core_models.CreateObjectResult
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Relations
@ -58,9 +59,7 @@ class CreateObjectAsMentionOrLinkTest {
fun setup() {
createObjectAsMentionOrLink = CreateObjectAsMentionOrLink(
repo = repo,
getDefaultPageType = getDefaultPageType,
dispatchers = dispatchers,
getTemplates = getTemplates,
spaceManager = spaceManager
)
stubSpaceManager()
@ -74,15 +73,19 @@ class CreateObjectAsMentionOrLinkTest {
val name = MockDataFactory.randomString()
val defaultTypeKey = MockDataFactory.randomString()
val defaultTemplate = MockDataFactory.randomString()
givenGetDefaultObjectType(
type = TypeKey(defaultTypeKey),
name = name,
defaultTemplate = defaultTemplate
)
stubCreateObject()
//TESTING
val params = CreateObjectAsMentionOrLink.Params(
name = name,
typeKey = type
typeKey = TypeKey(defaultTypeKey),
defaultTemplate = defaultTemplate
)
createObjectAsMentionOrLink.run(params)
@ -92,10 +95,10 @@ class CreateObjectAsMentionOrLinkTest {
prefilled = buildMap {
put(Relations.NAME, name)
},
template = null,
internalFlags = listOf(),
template = defaultTemplate,
internalFlags = listOf(InternalFlags.ShouldSelectTemplate, InternalFlags.ShouldSelectType),
space = SpaceId(spaceId),
type = TypeKey(defaultTypeKey)
typeKey = TypeKey(defaultTypeKey)
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
@ -119,7 +122,7 @@ class CreateObjectAsMentionOrLinkTest {
//TESTING
val params = CreateObjectAsMentionOrLink.Params(
name = name,
typeKey = type
typeKey = TypeKey(typeDefault)
)
createObjectAsMentionOrLink.run(params)
@ -129,9 +132,9 @@ class CreateObjectAsMentionOrLinkTest {
put(Relations.NAME, name)
},
template = null,
internalFlags = listOf(),
internalFlags = listOf(InternalFlags.ShouldSelectTemplate, InternalFlags.ShouldSelectType),
space = SpaceId(spaceId),
type = TypeKey(typeDefault)
typeKey = TypeKey(typeDefault)
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
@ -144,13 +147,12 @@ class CreateObjectAsMentionOrLinkTest {
val type = null
val name = MockDataFactory.randomString()
val typeDefault = MockDataFactory.randomString()
val typeDefaultId = MockDataFactory.randomString()
val typeDefaultName = MockDataFactory.randomString()
val template = MockDataFactory.randomString()
givenGetDefaultObjectType(
type = TypeKey(typeDefault),
name = typeDefaultName,
id = TypeId(typeDefaultId)
defaultTemplate = template
)
givenGetTemplates(listOf(ObjectWrapper.Basic(buildMap {
put(Relations.ID, template)
@ -160,7 +162,8 @@ class CreateObjectAsMentionOrLinkTest {
//TESTING
val params = CreateObjectAsMentionOrLink.Params(
name = name,
typeKey = type
typeKey = TypeKey(typeDefault),
defaultTemplate = template
)
createObjectAsMentionOrLink.run(params)
@ -170,9 +173,9 @@ class CreateObjectAsMentionOrLinkTest {
put(Relations.NAME, name)
},
template = template,
internalFlags = listOf(),
internalFlags = listOf(InternalFlags.ShouldSelectTemplate, InternalFlags.ShouldSelectType),
space = SpaceId(spaceId),
type = TypeKey(typeDefault)
typeKey = TypeKey(typeDefault)
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
@ -207,7 +210,7 @@ class CreateObjectAsMentionOrLinkTest {
//TESTING
val params = CreateObjectAsMentionOrLink.Params(
name = name,
typeKey = type,
typeKey = TypeKey(typeDefault),
)
createObjectAsMentionOrLink.run(params)
@ -218,23 +221,24 @@ class CreateObjectAsMentionOrLinkTest {
put(Relations.NAME, name)
},
template = null,
internalFlags = listOf(),
internalFlags = listOf(InternalFlags.ShouldSelectTemplate, InternalFlags.ShouldSelectType),
space = SpaceId(spaceId),
type = TypeKey(typeDefault)
typeKey = TypeKey(typeDefault)
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
private fun givenGetDefaultObjectType(
type: TypeKey? = null,
type: TypeKey,
name: String? = null,
id: TypeId? = null
defaultTemplate: String? = null
) {
getDefaultPageType.stub {
onBlocking { run(Unit) } doReturn GetDefaultPageType.Response(
type = type,
name = name,
id = id
id = TypeId(MockDataFactory.randomString()),
defaultTemplate = defaultTemplate
)
}
}

View file

@ -65,7 +65,7 @@ class CreateObjectTest {
}
@Test
fun `when type is null and default type is null - should send proper params`() = runBlocking {
fun `when type is null and default type not null - should send proper params`() = runBlocking {
//SETUP
val type = null
@ -74,7 +74,14 @@ class CreateObjectTest {
stubCreateObject()
//TESTING
val params = CreateObject.Param(type)
val params = CreateObject.Param(
type = type,
internalFlags = listOf(
InternalFlags.ShouldSelectType,
InternalFlags.ShouldSelectTemplate,
InternalFlags.ShouldEmptyDelete
)
)
createObject.run(params)
//ASSERT
@ -88,7 +95,7 @@ class CreateObjectTest {
InternalFlags.ShouldEmptyDelete
),
space = SpaceId(""),
type = appDefaultTypeKey
typeKey = appDefaultTypeKey
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
@ -107,7 +114,14 @@ class CreateObjectTest {
stubCreateObject()
//TESTING
val params = CreateObject.Param(type)
val params = CreateObject.Param(
type = type,
internalFlags = listOf(
InternalFlags.ShouldSelectType,
InternalFlags.ShouldSelectTemplate,
InternalFlags.ShouldEmptyDelete
)
)
createObject.run(params)
//ASSERT
@ -120,7 +134,7 @@ class CreateObjectTest {
InternalFlags.ShouldEmptyDelete
),
space = SpaceId(""),
type = TypeKey(defaultType)
typeKey = TypeKey(defaultType)
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
@ -137,13 +151,17 @@ class CreateObjectTest {
givenGetDefaultObjectType(
type = TypeKey(defaultType)
)
givenGetTemplates(listOf(ObjectWrapper.Basic(buildMap {
put(Relations.ID, templateBook)
})))
stubCreateObject()
//TESTING
val params = CreateObject.Param(type)
val params = CreateObject.Param(
type = type,
internalFlags = listOf(
InternalFlags.ShouldSelectType,
InternalFlags.ShouldSelectTemplate,
InternalFlags.ShouldEmptyDelete
)
)
createObject.run(params)
//ASSERT
@ -156,7 +174,7 @@ class CreateObjectTest {
InternalFlags.ShouldEmptyDelete
),
space = SpaceId(""),
type = TypeKey(defaultType)
typeKey = TypeKey(defaultType)
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
@ -171,7 +189,14 @@ class CreateObjectTest {
stubCreateObject()
//TESTING
val params = CreateObject.Param(TypeKey(type))
val params = CreateObject.Param(
type = TypeKey(type),
internalFlags = listOf(
InternalFlags.ShouldSelectType,
InternalFlags.ShouldSelectTemplate,
InternalFlags.ShouldEmptyDelete
)
)
createObject.run(params)
//ASSERT
@ -185,7 +210,7 @@ class CreateObjectTest {
InternalFlags.ShouldEmptyDelete
),
space = SpaceId(""),
type = TypeKey(type)
typeKey = TypeKey(type)
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
@ -197,13 +222,17 @@ class CreateObjectTest {
//SETUP
val type = MockDataFactory.randomString()
val template = MockDataFactory.randomString()
givenGetTemplates(listOf(ObjectWrapper.Basic(buildMap {
put(Relations.ID, template)
})))
stubCreateObject()
//TESTING
val params = CreateObject.Param(TypeKey(type))
val params = CreateObject.Param(
type = TypeKey(type),
internalFlags = listOf(
InternalFlags.ShouldSelectType,
InternalFlags.ShouldSelectTemplate,
InternalFlags.ShouldEmptyDelete
)
)
createObject.run(params)
//ASSERT
@ -217,7 +246,7 @@ class CreateObjectTest {
InternalFlags.ShouldEmptyDelete
),
space = SpaceId(""),
type = TypeKey(type)
typeKey = TypeKey(type)
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
@ -230,48 +259,47 @@ class CreateObjectTest {
val type = MockDataFactory.randomString()
val templateOne = MockDataFactory.randomString()
val templateTwo = MockDataFactory.randomString()
givenGetTemplates(
listOf(
ObjectWrapper.Basic(buildMap {
put(Relations.ID, templateOne)
}),
ObjectWrapper.Basic(buildMap {
put(Relations.ID, templateTwo)
})
)
)
stubCreateObject()
//TESTING
val params = CreateObject.Param(TypeKey(type))
val params = CreateObject.Param(
type = TypeKey(type),
internalFlags = listOf(
InternalFlags.ShouldSelectType,
InternalFlags.ShouldSelectTemplate,
InternalFlags.ShouldEmptyDelete
),
template = templateTwo
)
createObject.run(params)
//ASSERT
verifyNoInteractions(getDefaultPageType)
val commands = Command.CreateObject(
prefilled = emptyMap(),
template = null,
template = templateTwo,
internalFlags = listOf(
InternalFlags.ShouldSelectType,
InternalFlags.ShouldSelectTemplate,
InternalFlags.ShouldEmptyDelete
),
space = SpaceId(""),
type = TypeKey(type)
typeKey = TypeKey(type)
)
verifyBlocking(repo, times(1)) { createObject(commands) }
}
private fun givenGetDefaultObjectType(
type: TypeKey? = null,
type: TypeKey,
name: String? = null,
id: TypeId? = null
template: String? = null,
) {
getDefaultPageType.stub {
onBlocking { run(Unit) } doReturn GetDefaultPageType.Response(
type = type,
name = name,
id = id
id = TypeId(MockDataFactory.randomString()),
defaultTemplate = template
)
}
}

View file

@ -864,7 +864,7 @@ class Middleware @Inject constructor(
templateId = command.template.orEmpty(),
internalFlags = command.internalFlags.toMiddlewareModel(),
spaceId = command.space.id,
objectTypeUniqueKey = command.type.key
objectTypeUniqueKey = command.typeKey.key
)
if (BuildConfig.DEBUG) logRequest(request)
val response = service.objectCreate(request)
@ -885,7 +885,8 @@ class Middleware @Inject constructor(
internalFlags = command.internalFlags.toMiddlewareModel(),
targetId = command.target,
position = command.position.toMiddlewareModel(),
fields = null
fields = null,
spaceId = command.space
)
if (BuildConfig.DEBUG) logRequest(request)

View file

@ -27,7 +27,6 @@ import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoMoreInteractions
typealias CBlock = com.anytypeio.anytype.core_models.Block
typealias CFields = com.anytypeio.anytype.core_models.Block.Fields
typealias CBlockFileType = com.anytypeio.anytype.core_models.Block.Content.File.Type
typealias CBlockPrototypeText = com.anytypeio.anytype.core_models.Block.Prototype.Text
@ -79,6 +78,7 @@ class MiddlewareTest {
// SETUP
val templateId = MockDataFactory.randomUuid()
val spaceId = MockDataFactory.randomUuid()
val typeKey = TypeKey(MockDataFactory.randomUuid())
@ -89,7 +89,8 @@ class MiddlewareTest {
template = templateId,
prefilled = emptyMap(),
internalFlags = listOf(),
type = typeKey
type = typeKey,
space = spaceId
)
val response = Rpc.BlockLink.CreateWithObject.Response(
@ -104,7 +105,8 @@ class MiddlewareTest {
position = Block.Position.Inner,
details = mapOf<String, Any?>(),
templateId = templateId,
objectTypeUniqueKey = typeKey.key
objectTypeUniqueKey = typeKey.key,
spaceId = spaceId
)
service.stub {
@ -136,6 +138,7 @@ class MiddlewareTest {
val name = MockDataFactory.randomString()
val typeKey = TypeKey(MockDataFactory.randomUuid())
val spaceId = MockDataFactory.randomUuid()
val command = Command.CreateBlockLinkWithObject(
context = MockDataFactory.randomUuid(),
@ -144,7 +147,8 @@ class MiddlewareTest {
template = null,
prefilled = buildMap { put(Relations.NAME, name) },
internalFlags = listOf(),
type = typeKey
type = typeKey,
space = spaceId
)
val response = Rpc.BlockLink.CreateWithObject.Response(
@ -158,7 +162,8 @@ class MiddlewareTest {
targetId = command.target,
position = Block.Position.Inner,
details = buildMap { put(Relations.NAME, name) },
objectTypeUniqueKey = typeKey.key
objectTypeUniqueKey = typeKey.key,
spaceId = spaceId
)
service.stub {

View file

@ -231,6 +231,7 @@ import com.anytypeio.anytype.presentation.relations.views
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
import com.anytypeio.anytype.presentation.search.ObjectSearchViewModel
import com.anytypeio.anytype.presentation.spaces.SpaceGradientProvider
import com.anytypeio.anytype.presentation.templates.TemplateView.Companion.DEFAULT_TEMPLATE_ID_BLANK
import com.anytypeio.anytype.presentation.util.CopyFileStatus
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
import com.anytypeio.anytype.presentation.util.Dispatcher
@ -3092,8 +3093,7 @@ class EditorViewModel(
}
private fun onAddNewObjectClicked(
typeId: TypeId,
typeKey: TypeKey
objectTypeView: ObjectTypeView
) {
controlPanelInteractor.onEvent(ControlPanelMachine.Event.OnAddBlockToolbarOptionSelected)
@ -3123,17 +3123,18 @@ class EditorViewModel(
}
}
val params = CreateBlockLinkWithObject.Params(
context = context,
position = position,
target = target,
typeId = typeId,
typeKey = typeKey
)
val startTime = System.currentTimeMillis()
viewModelScope.launch {
val params = CreateBlockLinkWithObject.Params(
context = context,
position = position,
target = target,
typeId = TypeId(objectTypeView.id),
typeKey = TypeKey(objectTypeView.key),
template = objectTypeView.defaultTemplate,
space = spaceManager.get()
)
createBlockLinkWithObject.async(
params = params
).fold(
@ -3144,7 +3145,7 @@ class EditorViewModel(
orchestrator.proxies.payloads.send(result.payload)
sendAnalyticsObjectCreateEvent(
analytics = analytics,
type = typeId.id,
type = objectTypeView.key,
storeOfObjectTypes = storeOfObjectTypes,
route = EventsDictionary.Routes.objPowerTool,
startTime = startTime
@ -3157,30 +3158,49 @@ class EditorViewModel(
fun onAddNewDocumentClicked() {
Timber.d("onAddNewDocumentClicked, ")
proceedWithCreatingNewObject(type = null, template = null)
proceedWithCreatingNewObject(
typeKey = null,
template = null,
internalFlags = listOf(
InternalFlags.ShouldSelectTemplate,
InternalFlags.ShouldSelectType,
InternalFlags.ShouldEmptyDelete
)
)
}
fun onCreateObjectWithTemplateClicked(template: Id) {
Timber.d("onCreateObjectWithTemplateClicked, template:[$template]")
val objType = getObjectTypeFromDetails() ?: return
proceedWithCreatingNewObject(type = objType, template = template)
val typeKey = getObjectTypeFromDetails() ?: return
proceedWithCreatingNewObject(
typeKey = TypeKey(typeKey),
template = template,
internalFlags = listOf(
InternalFlags.ShouldSelectTemplate,
InternalFlags.ShouldEmptyDelete
)
)
}
private fun proceedWithCreatingNewObject(type: Id?, template: Id?) {
private fun proceedWithCreatingNewObject(
typeKey: TypeKey?,
template: Id?,
internalFlags: List<InternalFlags> = emptyList()
) {
val startTime = System.currentTimeMillis()
viewModelScope.launch {
val params = CreateObject.Param(
type = TODO("You need to pass unique key"),
template = template
type = typeKey,
template = template,
internalFlags = internalFlags,
)
createObject.async(params = params)
.fold(
onSuccess = { result ->
sendAnalyticsObjectCreateEvent(
analytics = analytics,
type = result.objectId,
type = result.typeKey.key,
storeOfObjectTypes = storeOfObjectTypes,
route = EventsDictionary.Routes.objPowerTool,
startTime = startTime
@ -4678,10 +4698,7 @@ class EditorViewModel(
is SlashItem.ObjectType -> {
cutSlashFilter(targetId = targetId)
controlPanelInteractor.onEvent(ControlPanelMachine.Event.Slash.OnStop)
onAddNewObjectClicked(
typeId = TypeId(item.objectTypeView.id),
typeKey = TypeKey(item.objectTypeView.key)
)
onAddNewObjectClicked(objectTypeView = item.objectTypeView)
}
is SlashItem.Relation -> {
val isBlockEmpty = cutSlashFilter(targetId = targetId)
@ -5711,17 +5728,13 @@ class EditorViewModel(
getDefaultPageType.async(Unit).fold(
onFailure = {
Timber.e(it, "Error while getting default object type")
proceedWithCreateNewObject(
typeKey = null,
typeId = null,
mentionText = mentionText
)
sendToast("Error while getting default object type, couldn't create a new mention")
},
onSuccess = { result ->
proceedWithCreateNewObject(
typeKey = result.type,
typeId = result.id,
mentionText = mentionText
mentionText = mentionText,
templateId = result.defaultTemplate
)
}
)
@ -5729,15 +5742,15 @@ class EditorViewModel(
}
private fun proceedWithCreateNewObject(
typeId: TypeId?,
typeKey: TypeKey?,
mentionText: String
typeKey: TypeKey,
mentionText: String,
templateId: Id?
) {
val params = CreateObjectAsMentionOrLink.Params(
name = mentionText.removePrefix(MENTION_PREFIX),
typeKey = typeKey,
typeId = typeId
defaultTemplate = if (templateId == DEFAULT_TEMPLATE_ID_BLANK) null else templateId
)
val startTime = System.currentTimeMillis()
@ -5757,7 +5770,7 @@ class EditorViewModel(
)
sendAnalyticsObjectCreateEvent(
analytics = analytics,
type = typeId?.id,
type = typeKey.key,
storeOfObjectTypes = storeOfObjectTypes,
route = EventsDictionary.Routes.objCreateMention,
startTime = startTime
@ -6060,7 +6073,8 @@ class EditorViewModel(
createObjectAddProceedToAddToTextAsLink(
name = name,
typeKey = response.type,
typeId = response.id
typeId = response.id,
templateId = response.defaultTemplate
)
}
)
@ -6090,14 +6104,15 @@ class EditorViewModel(
private suspend fun createObjectAddProceedToAddToTextAsLink(
name: String,
typeKey: TypeKey?,
typeId: TypeId?
typeKey: TypeKey,
typeId: TypeId?,
templateId: Id?
) {
val startTime = System.currentTimeMillis()
val params = CreateObjectAsMentionOrLink.Params(
name = name,
typeKey = typeKey,
typeId = typeId
defaultTemplate = if (templateId == DEFAULT_TEMPLATE_ID_BLANK) null else templateId
)
createObjectAsMentionOrLink.async(params).fold(
onFailure = { Timber.e(it, "Error while creating new page with params: $params") },
@ -6258,8 +6273,10 @@ class EditorViewModel(
private fun getObjectTypeFromDetails(): Id? {
val details = orchestrator.stores.details.current()
val wrapper = ObjectWrapper.Basic(details.details[context]?.map ?: emptyMap())
return wrapper.getProperType()
val currentObject = ObjectWrapper.Basic(details.details[context]?.map ?: emptyMap())
val currentObjectTypeId = currentObject.getProperType() ?: return null
val currentObjectType = ObjectWrapper.Basic(details.details[currentObjectTypeId]?.map ?: emptyMap())
return currentObjectType.uniqueKey
}
fun isObjectTemplate(): Boolean {

View file

@ -9,6 +9,8 @@ import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_models.primitives.TypeId
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.domain.config.DebugSettings
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.ObjectStore
@ -603,7 +605,8 @@ fun ObjectWrapper.Type.toObjectTypeView(selectedSources: List<Id> = emptyList())
name = name.orEmpty(),
emoji = iconEmoji,
description = description,
isSelected = selectedSources.contains(id)
isSelected = selectedSources.contains(id),
defaultTemplate = defaultTemplateId
)
fun List<ObjectType.Layout>.toView(): List<ObjectLayoutView> = mapNotNull { layout ->

View file

@ -22,7 +22,8 @@ data class ObjectTypeView(
val name: String,
val description: String?,
val emoji: String?,
val isSelected: Boolean = false
val isSelected: Boolean = false,
val defaultTemplate: Id? = null
)
class ObjectTypeViewComparator : Comparator<ObjectTypeView> {

View file

@ -654,7 +654,8 @@ object ObjectSearchConstants {
Relations.IS_DELETED,
Relations.SMARTBLOCKTYPES,
Relations.SOURCE_OBJECT,
Relations.RECOMMENDED_LAYOUT
Relations.RECOMMENDED_LAYOUT,
Relations.DEFAULT_TEMPLATE_ID
)
//endregion

View file

@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerCardSize
import com.anytypeio.anytype.core_models.DVViewerType
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectTypeIds
@ -1365,14 +1366,19 @@ class ObjectSetViewModel(
val startTime = System.currentTimeMillis()
jobs += viewModelScope.launch {
createObject.async(CreateObject.Param(type = null)).fold(
createObject.async(
CreateObject.Param(
type = null,
internalFlags = listOf(InternalFlags.ShouldSelectType, InternalFlags.ShouldSelectTemplate)
)
).fold(
onSuccess = { result ->
proceedWithOpeningObject(result.objectId)
sendAnalyticsObjectCreateEvent(
analytics = analytics,
startTime = startTime,
storeOfObjectTypes = storeOfObjectTypes,
type = result.type.key,
type = result.typeKey.key,
route = EventsDictionary.Routes.navigation,
view = EventsDictionary.View.viewNavbar
)

View file

@ -3787,16 +3787,6 @@ open class EditorViewModelTest {
}
}
private fun stubGetDefaultObjectType(type: String? = null, name: String? = null) {
getDefaultPageType.stub {
onBlocking { run(Unit) } doReturn GetDefaultPageType.Response(
type = type?.let { TypeKey((it)) },
name = name,
id = null
)
}
}
lateinit var getObjectTypes: GetObjectTypes
lateinit var addRelationToObject: AddRelationToObject

View file

@ -196,57 +196,57 @@ class EditorInternalFlagsTest : EditorPresentationTestSetup() {
coroutineTestRule.advanceTime(100)
}
@Test
fun `should remove template flag on start template selection widget`() = runTest {
val title = StubTitle()
val header = StubHeader(children = listOf(title.id))
val page = StubSmartBlock(id = root, children = listOf(header.id))
val document = listOf(page, header, title)
stubInterceptEvents()
val detailsList = Block.Details(
details = mapOf(
root to Block.Fields(
mapOf(
Relations.TYPE to ObjectTypeIds.PAGE,
Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble(),
Relations.INTERNAL_FLAGS to listOf(
InternalFlags.ShouldSelectTemplate.code.toDouble(),
InternalFlags.ShouldEmptyDelete.code.toDouble(),
)
)
)
)
)
stubOpenDocument(document = document, details = detailsList)
stubGetObjectTypes(types = emptyList())
stubGetDefaultObjectType()
val vm = buildViewModel()
stubFileLimitEvents()
stubSetInternalFlags()
vm.onStart(root)
advanceUntilIdle()
vm.onObjectTypesWidgetDoneClicked()
advanceUntilIdle()
verifyBlocking(setObjectInternalFlags, times(1)) {
async(
params = SetObjectInternalFlags.Params(
ctx = root,
flags = listOf(
InternalFlags.ShouldEmptyDelete
)
)
)
}
coroutineTestRule.advanceTime(100)
}
// @Test
// fun `should remove template flag on start template selection widget`() = runTest {
// val title = StubTitle()
// val header = StubHeader(children = listOf(title.id))
// val page = StubSmartBlock(id = root, children = listOf(header.id))
// val document = listOf(page, header, title)
// stubInterceptEvents()
//
// val detailsList = Block.Details(
// details = mapOf(
// root to Block.Fields(
// mapOf(
// Relations.TYPE to ObjectTypeIds.PAGE,
// Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble(),
// Relations.INTERNAL_FLAGS to listOf(
// InternalFlags.ShouldSelectTemplate.code.toDouble(),
// InternalFlags.ShouldEmptyDelete.code.toDouble(),
// )
// )
// )
// )
// )
// stubOpenDocument(document = document, details = detailsList)
// stubGetObjectTypes(types = emptyList())
// stubGetDefaultObjectType()
//
// val vm = buildViewModel()
//
// stubFileLimitEvents()
// stubSetInternalFlags()
//
// vm.onStart(root)
//
// advanceUntilIdle()
// vm.onObjectTypesWidgetDoneClicked()
//
// advanceUntilIdle()
//
// verifyBlocking(setObjectInternalFlags, times(1)) {
// async(
// params = SetObjectInternalFlags.Params(
// ctx = root,
// flags = listOf(
// InternalFlags.ShouldEmptyDelete
// )
// )
// )
// }
//
// coroutineTestRule.advanceTime(100)
// }
@Test
fun `should not remove template flag on start template selection widget when flag isn't present`() = runTest {

View file

@ -706,7 +706,8 @@ open class EditorPresentationTestSetup {
fun stubGetDefaultObjectType(
id: String = MockDataFactory.randomString(),
type: String = MockDataFactory.randomString(),
name: String? = null
name: String? = null,
template: String? = null
) {
getDefaultPageType.stub {
onBlocking { async(Unit) } doReturn Resultat.success(
@ -714,6 +715,7 @@ open class EditorPresentationTestSetup {
id = TypeId(id),
type = TypeKey(type),
name = name,
defaultTemplate = template
)
)
}
@ -765,9 +767,9 @@ open class EditorPresentationTestSetup {
}
}
fun stubSpaceManager() {
fun stubSpaceManager(space: String = "") {
spaceManager.stub {
onBlocking { get() } doReturn ""
onBlocking { get() } doReturn space
}
}
}

View file

@ -18,6 +18,7 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashItem
import com.anytypeio.anytype.presentation.objects.ObjectTypeView
import com.anytypeio.anytype.presentation.objects.getProperName
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import net.bytebuddy.utility.RandomString
import org.junit.After
import org.junit.Before
import org.junit.Rule
@ -45,6 +46,8 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
coroutineTestRule.advanceTime(TEXT_CHANGES_DEBOUNCE_DURATION)
}
val space = "spaceId-${RandomString.make(10)}"
@Test
fun `should invoke CreateBlockLinkWithObject UseCase on clicked on object type item with bottom position when text block is not empty`() {
// SETUP
@ -60,6 +63,7 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
stubSearchObjects(listOf(type1, type2, type3))
stubCreateBlockLinkWithObject(root, a.id)
stubOpenDocument(doc)
stubSpaceManager(space = space)
val vm = buildViewModel()
vm.onStart(root)
@ -93,7 +97,9 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
target = a.id,
position = Position.BOTTOM,
typeId = TypeId(type2.id),
typeKey = TypeKey(type2.getValue<Key>(Relations.UNIQUE_KEY)!!)
typeKey = TypeKey(type2.getValue<Key>(Relations.UNIQUE_KEY)!!),
space = space,
template = null
)
verifyBlocking(createBlockLinkWithObject, times(1)) { async(params) }
@ -117,6 +123,7 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
stubSearchObjects(listOf(type1, type2, type3))
stubCreateBlockLinkWithObject(root, paragraph.id)
stubOpenDocument(doc)
stubSpaceManager(space = space)
val vm = buildViewModel()
vm.onStart(root)
@ -150,7 +157,9 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
target = paragraph.id,
position = Position.REPLACE,
typeId = TypeId(type2.id),
typeKey = TypeKey(type2.getValue(Relations.UNIQUE_KEY)!!)
typeKey = TypeKey(type2.getValue(Relations.UNIQUE_KEY)!!),
space = space,
template = null
)
verifyBlocking(createBlockLinkWithObject, times(1)) { async(params) }

View file

@ -24,6 +24,8 @@ import com.anytypeio.anytype.core_models.StubObjectView
import com.anytypeio.anytype.core_models.StubSmartBlock
import com.anytypeio.anytype.core_models.StubWidgetBlock
import com.anytypeio.anytype.core_models.WidgetSession
import com.anytypeio.anytype.core_models.primitives.TypeId
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.Resultat
import com.anytypeio.anytype.domain.bin.EmptyBin
@ -2686,15 +2688,21 @@ class HomeScreenViewModelTest {
}
}
private fun stubGetDefaultPageType() {
private fun stubGetDefaultPageType(
id: TypeId = TypeId(MockDataFactory.randomUuid()),
type: TypeKey = TypeKey(MockDataFactory.randomUuid()),
name: String = MockDataFactory.randomString(),
template: String? = null
) {
getDefaultPageType.stub {
onBlocking {
execute(any())
} doReturn Resultat.Success(
GetDefaultPageType.Response(
id = null,
type = null,
name = null
id = id,
type = type,
name = name,
defaultTemplate = template
)
)
}

View file

@ -11,6 +11,7 @@ import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.SearchResult
import com.anytypeio.anytype.core_models.primitives.TypeId
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.core_models.restrictions.DataViewRestrictions
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
@ -405,12 +406,18 @@ open class ObjectSetViewModelTestSetup {
storeOfObjectTypes.set(id, map)
}
fun stubGetDefaultPageType(type: TypeKey = defaultObjectPageType, name: String = defaultObjectPageTypeName) {
fun stubGetDefaultPageType(
type: TypeKey = defaultObjectPageType,
name: String = defaultObjectPageTypeName,
id: TypeId = TypeId(MockDataFactory.randomString()),
template: Id? = null
) {
getDefaultPageType.stub {
onBlocking { run(Unit) } doReturn GetDefaultPageType.Response(
type = type,
name = name,
id = null
id = id,
defaultTemplate = template
)
}
}