Skip to content

Commit

Permalink
Merge pull request #6320 from vector-im/feature/ons/poll_unit_tests
Browse files Browse the repository at this point in the history
CreatePollViewModel unit tests [PSF-1122]
  • Loading branch information
onurays authored Jun 17, 2022
2 parents 674e538 + 712a38e commit 242cc28
Show file tree
Hide file tree
Showing 9 changed files with 490 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog.d/6320.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CreatePollViewModel unit tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package im.vector.app.features.poll.create

import com.airbnb.mvrx.test.MvRxTestRule
import im.vector.app.features.poll.PollMode
import im.vector.app.test.fakes.FakeCreatePollViewStates.A_FAKE_OPTIONS
import im.vector.app.test.fakes.FakeCreatePollViewStates.A_FAKE_QUESTION
import im.vector.app.test.fakes.FakeCreatePollViewStates.A_FAKE_ROOM_ID
import im.vector.app.test.fakes.FakeCreatePollViewStates.A_POLL_START_TIMELINE_EVENT
import im.vector.app.test.fakes.FakeCreatePollViewStates.createPollArgs
import im.vector.app.test.fakes.FakeCreatePollViewStates.editPollArgs
import im.vector.app.test.fakes.FakeCreatePollViewStates.editedPollViewState
import im.vector.app.test.fakes.FakeCreatePollViewStates.initialCreatePollViewState
import im.vector.app.test.fakes.FakeCreatePollViewStates.pollViewStateWithOnlyQuestion
import im.vector.app.test.fakes.FakeCreatePollViewStates.pollViewStateWithQuestionAndEnoughOptions
import im.vector.app.test.fakes.FakeCreatePollViewStates.pollViewStateWithQuestionAndEnoughOptionsButDeletedLastOption
import im.vector.app.test.fakes.FakeCreatePollViewStates.pollViewStateWithQuestionAndMaxOptions
import im.vector.app.test.fakes.FakeCreatePollViewStates.pollViewStateWithQuestionAndNotEnoughOptions
import im.vector.app.test.fakes.FakeCreatePollViewStates.pollViewStateWithoutQuestionAndEnoughOptions
import im.vector.app.test.fakes.FakeSession
import im.vector.app.test.test
import io.mockk.unmockkAll
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.matrix.android.sdk.api.session.room.model.message.PollType

class CreatePollViewModelTest {

private val testDispatcher = UnconfinedTestDispatcher()

@get:Rule
val mvRxTestRule = MvRxTestRule(
testDispatcher = testDispatcher // See https://github.com/airbnb/mavericks/issues/599
)

private val fakeSession = FakeSession()

private fun createPollViewModel(pollMode: PollMode): CreatePollViewModel {
return if (pollMode == PollMode.EDIT) {
CreatePollViewModel(CreatePollViewState(editPollArgs), fakeSession)
} else {
CreatePollViewModel(CreatePollViewState(createPollArgs), fakeSession)
}
}

@Before
fun setup() {
fakeSession
.roomService()
.getRoom(A_FAKE_ROOM_ID)
.timelineService()
.givenTimelineEvent(A_POLL_START_TIMELINE_EVENT)
}

@After
fun tearDown() {
unmockkAll()
}

@Test
fun `given the view model is initialized then poll cannot be created and more options can be added`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

test
.assertLatestState(initialCreatePollViewState)
.finish()
}

@Test
fun `given there is not any options when the question is added then poll cannot be created and more options can be added`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

createPollViewModel.handle(CreatePollAction.OnQuestionChanged(A_FAKE_QUESTION))

test
.assertLatestState(pollViewStateWithOnlyQuestion)
.finish()
}

@Test
fun `given there is not enough options when the question is added then poll cannot be created and more options can be added`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

createPollViewModel.handle(CreatePollAction.OnQuestionChanged(A_FAKE_QUESTION))
repeat(CreatePollViewModel.MIN_OPTIONS_COUNT - 1) {
createPollViewModel.handle(CreatePollAction.OnOptionChanged(it, A_FAKE_OPTIONS[it]))
}

test
.assertLatestState(pollViewStateWithQuestionAndNotEnoughOptions)
.finish()
}

@Test
fun `given there is not a question when enough options are added then poll cannot be created and more options can be added`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

repeat(CreatePollViewModel.MIN_OPTIONS_COUNT) {
createPollViewModel.handle(CreatePollAction.OnOptionChanged(it, A_FAKE_OPTIONS[it]))
}

test
.assertLatestState(pollViewStateWithoutQuestionAndEnoughOptions)
.finish()
}

@Test
fun `given there is a question when enough options are added then poll can be created and more options can be added`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

createPollViewModel.handle(CreatePollAction.OnQuestionChanged(A_FAKE_QUESTION))
repeat(CreatePollViewModel.MIN_OPTIONS_COUNT) {
createPollViewModel.handle(CreatePollAction.OnOptionChanged(it, A_FAKE_OPTIONS[it]))
}

test
.assertLatestState(pollViewStateWithQuestionAndEnoughOptions)
.finish()
}

@Test
fun `given there is a question when max number of options are added then poll can be created and more options cannot be added`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

createPollViewModel.handle(CreatePollAction.OnQuestionChanged(A_FAKE_QUESTION))
repeat(CreatePollViewModel.MAX_OPTIONS_COUNT) {
if (it >= CreatePollViewModel.MIN_OPTIONS_COUNT) {
createPollViewModel.handle(CreatePollAction.OnAddOption)
}
createPollViewModel.handle(CreatePollAction.OnOptionChanged(it, A_FAKE_OPTIONS[it]))
}

test
.assertLatestState(pollViewStateWithQuestionAndMaxOptions)
.finish()
}

@Test
fun `given an initial poll state when poll type is changed then view state is updated accordingly`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

createPollViewModel.handle(CreatePollAction.OnPollTypeChanged(PollType.UNDISCLOSED))
createPollViewModel.handle(CreatePollAction.OnPollTypeChanged(PollType.DISCLOSED))

test
.assertStatesChanges(
initialCreatePollViewState,
{ copy(pollType = PollType.UNDISCLOSED) },
{ copy(pollType = PollType.DISCLOSED) },
)
.finish()
}

@Test
fun `given there is not a question and enough options when create poll is requested then error view events are post`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

createPollViewModel.handle(CreatePollAction.OnCreatePoll)

createPollViewModel.handle(CreatePollAction.OnQuestionChanged(A_FAKE_QUESTION))
createPollViewModel.handle(CreatePollAction.OnCreatePoll)

createPollViewModel.handle(CreatePollAction.OnOptionChanged(0, A_FAKE_OPTIONS[0]))
createPollViewModel.handle(CreatePollAction.OnCreatePoll)

test
.assertEvents(
CreatePollViewEvents.EmptyQuestionError,
CreatePollViewEvents.NotEnoughOptionsError(requiredOptionsCount = CreatePollViewModel.MIN_OPTIONS_COUNT),
CreatePollViewEvents.NotEnoughOptionsError(requiredOptionsCount = CreatePollViewModel.MIN_OPTIONS_COUNT),
)
}

@Test
fun `given there is a question and enough options when create poll is requested then success view event is post`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

createPollViewModel.handle(CreatePollAction.OnQuestionChanged(A_FAKE_QUESTION))
createPollViewModel.handle(CreatePollAction.OnOptionChanged(0, A_FAKE_OPTIONS[0]))
createPollViewModel.handle(CreatePollAction.OnOptionChanged(1, A_FAKE_OPTIONS[1]))
createPollViewModel.handle(CreatePollAction.OnCreatePoll)

test
.assertEvents(
CreatePollViewEvents.Success,
)
}

@Test
fun `given there is a question and enough options when the last option is deleted then view state should be updated accordingly`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.CREATE)
val test = createPollViewModel.test()

createPollViewModel.handle(CreatePollAction.OnQuestionChanged(A_FAKE_QUESTION))
createPollViewModel.handle(CreatePollAction.OnOptionChanged(0, A_FAKE_OPTIONS[0]))
createPollViewModel.handle(CreatePollAction.OnOptionChanged(1, A_FAKE_OPTIONS[1]))
createPollViewModel.handle(CreatePollAction.OnDeleteOption(1))

test.assertLatestState(pollViewStateWithQuestionAndEnoughOptionsButDeletedLastOption)
}

@Test
fun `given an edited poll event when question and options are changed then view state is updated accordingly`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.EDIT)
val test = createPollViewModel.test()

test
.assertState(editedPollViewState)
.finish()
}

@Test
fun `given an edited poll event then able to be edited`() = runTest {
val createPollViewModel = createPollViewModel(PollMode.EDIT)
val test = createPollViewModel.test()

createPollViewModel.handle(CreatePollAction.OnCreatePoll)

test
.assertEvents(
CreatePollViewEvents.Success,
)
}
}
5 changes: 5 additions & 0 deletions vector/src/test/java/im/vector/app/test/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ class ViewModelTest<S, VE>(
return this
}

fun assertLatestState(expected: S): ViewModelTest<S, VE> {
states.assertLatestValue(expected)
return this
}

fun finish() {
states.finish()
viewEvents.finish()
Expand Down
4 changes: 4 additions & 0 deletions vector/src/test/java/im/vector/app/test/FlowTestObserver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ class FlowTestObserver<T>(
return this
}

fun assertLatestValue(value: T) {
assertTrue(values.last() == value)
}

fun assertValues(values: List<T>): FlowTestObserver<T> {
assertEquals(values, this.values)
return this
Expand Down
Loading

0 comments on commit 242cc28

Please sign in to comment.