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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@
import com.d4rk.androidtutorials.java.ui.screens.android.repository.LessonRepository;

public class CodeViewModel extends ViewModel {
private final MutableLiveData<LessonRepository.Lesson> lesson = new MutableLiveData<>();
private final LessonRepository repository = new LessonRepository();
private final GetLessonUseCase getLessonUseCase = new GetLessonUseCase(repository);
private final MutableLiveData<com.d4rk.androidtutorials.java.data.repository.LessonRepository.Lesson> lesson = new MutableLiveData<>();
private final GetLessonUseCase getLessonUseCase;

public CodeViewModel() {
this(new GetLessonUseCase(new LessonRepository()));
}

CodeViewModel(GetLessonUseCase getLessonUseCase) {
this.getLessonUseCase = getLessonUseCase;
}

public void setLessonName(String lessonName) {
lesson.setValue(getLessonUseCase.invoke(lessonName));
}

public LiveData<LessonRepository.Lesson> getLesson() {
public LiveData<com.d4rk.androidtutorials.java.data.repository.LessonRepository.Lesson> getLesson() {
return lesson;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.d4rk.androidtutorials.java.ui.screens.android;

import static org.junit.Assert.assertEquals;

import androidx.arch.core.executor.testing.InstantTaskExecutorRule;

import com.d4rk.androidtutorials.java.data.repository.LessonRepository;
import com.d4rk.androidtutorials.java.domain.android.GetLessonUseCase;

import org.junit.Rule;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

public class CodeViewModelTest {

@Rule
public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();

@Test
public void setLessonName_updatesLiveData() {
FakeLessonRepository repository = new FakeLessonRepository();
LessonRepository.Lesson expected = new LessonRepository.Lesson(1, 2, 3);
repository.addLesson("lesson", expected);
CodeViewModel viewModel = new CodeViewModel(new GetLessonUseCase(repository));

viewModel.setLessonName("lesson");

assertEquals(expected, viewModel.getLesson().getValue());
}

@Test(expected = IllegalArgumentException.class)
public void setLessonName_unknownLessonThrows() {
FakeLessonRepository repository = new FakeLessonRepository();
CodeViewModel viewModel = new CodeViewModel(new GetLessonUseCase(repository));

viewModel.setLessonName("unknown");
}

private static final class FakeLessonRepository implements LessonRepository {
private final Map<String, Lesson> lessons = new HashMap<>();

void addLesson(String name, Lesson lesson) {
lessons.put(name, lesson);
}

@Override
public Lesson getLesson(String lessonName) {
Lesson lesson = lessons.get(lessonName);
if (lesson == null) {
throw new IllegalArgumentException("Unknown lesson: " + lessonName);
}
return lesson;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.d4rk.androidtutorials.java.ui.screens.help;

import static org.junit.Assert.assertSame;

import android.app.Activity;

import com.d4rk.androidtutorials.java.data.repository.HelpRepository;
import com.d4rk.androidtutorials.java.domain.help.LaunchReviewFlowUseCase;
import com.d4rk.androidtutorials.java.domain.help.RequestReviewFlowUseCase;
import com.google.android.play.core.review.ReviewInfo;

import org.junit.Test;
import org.mockito.Mockito;

public class HelpViewModelTest {

@Test
public void requestReviewFlowDelegatesToRepository() {
FakeHelpRepository repository = new FakeHelpRepository();
HelpViewModel viewModel = new HelpViewModel(
new RequestReviewFlowUseCase(repository),
new LaunchReviewFlowUseCase(repository)
);
HelpRepository.OnReviewInfoListener listener = Mockito.mock(HelpRepository.OnReviewInfoListener.class);

viewModel.requestReviewFlow(listener);

assertSame(listener, repository.lastListener);
}

@Test
public void launchReviewFlowDelegatesToRepository() {
FakeHelpRepository repository = new FakeHelpRepository();
HelpViewModel viewModel = new HelpViewModel(
new RequestReviewFlowUseCase(repository),
new LaunchReviewFlowUseCase(repository)
);
Activity activity = Mockito.mock(Activity.class);
ReviewInfo info = Mockito.mock(ReviewInfo.class);

viewModel.launchReviewFlow(activity, info);

assertSame(activity, repository.lastActivity);
assertSame(info, repository.lastReviewInfo);
}

private static final class FakeHelpRepository implements HelpRepository {
private HelpRepository.OnReviewInfoListener lastListener;
private Activity lastActivity;
private ReviewInfo lastReviewInfo;

@Override
public void requestReviewFlow(OnReviewInfoListener listener) {
lastListener = listener;
}

@Override
public void launchReviewFlow(Activity activity, ReviewInfo reviewInfo) {
lastActivity = activity;
lastReviewInfo = reviewInfo;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import android.content.Intent;
import android.net.Uri;

import androidx.arch.core.executor.testing.InstantTaskExecutorRule;

import com.d4rk.androidtutorials.java.data.model.PromotedApp;
Expand All @@ -16,7 +19,10 @@
import org.junit.Rule;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class HomeViewModelTest {
Expand All @@ -28,12 +34,7 @@ public class HomeViewModelTest {
public void uiStateUpdatesWithData() {
List<PromotedApp> promoted = List.of(new PromotedApp("App", "pkg", "icon"));
FakeHomeRepository repo = new FakeHomeRepository(promoted);
HomeViewModel viewModel = new HomeViewModel(
new GetDailyTipUseCase(repo),
new GetPromotedAppsUseCase(repo),
new GetPlayStoreUrlUseCase(repo),
new GetAppPlayStoreUrlUseCase(repo)
);
HomeViewModel viewModel = createViewModel(repo);
viewModel.setAnnouncements("Title", "Subtitle");

HomeUiState state = viewModel.getUiState().getValue();
Expand All @@ -47,39 +48,118 @@ public void uiStateUpdatesWithData() {
@Test
public void uiStateHandlesEmptyPromotedApps() {
FakeHomeRepository repo = new FakeHomeRepository(List.of());
HomeViewModel viewModel = new HomeViewModel(
new GetDailyTipUseCase(repo),
new GetPromotedAppsUseCase(repo),
new GetPlayStoreUrlUseCase(repo),
new GetAppPlayStoreUrlUseCase(repo)
);
HomeViewModel viewModel = createViewModel(repo);
viewModel.setAnnouncements("Title", "Subtitle");

HomeUiState state = viewModel.getUiState().getValue();
assertNotNull(state);
assertTrue(state.promotedApps().isEmpty());
}

record FakeHomeRepository(List<PromotedApp> apps) implements HomeRepository {
@Test
public void promotedAppsLimitedToAtMostFour() {
List<PromotedApp> promoted = List.of(
new PromotedApp("App1", "pkg1", "icon1"),
new PromotedApp("App2", "pkg2", "icon2"),
new PromotedApp("App3", "pkg3", "icon3"),
new PromotedApp("App4", "pkg4", "icon4"),
new PromotedApp("App5", "pkg5", "icon5")
);
FakeHomeRepository repo = new FakeHomeRepository(promoted);
HomeViewModel viewModel = createViewModel(repo);

HomeUiState state = viewModel.getUiState().getValue();
assertNotNull(state);
assertTrue(state.promotedApps().size() <= 4);
}

@Test
public void getOpenPlayStoreIntent_buildsViewIntent() {
FakeHomeRepository repo = new FakeHomeRepository(List.of());
String expectedUrl = "https://play.google.com/store/apps/details?id=com.example";
repo.setPlayStoreUrl(expectedUrl);
HomeViewModel viewModel = createViewModel(repo);

Intent intent = viewModel.getOpenPlayStoreIntent();

assertEquals(Intent.ACTION_VIEW, intent.getAction());
assertEquals(Uri.parse(expectedUrl), intent.getData());
}

@Test
public void getPromotedAppIntent_buildsViewIntent() {
FakeHomeRepository repo = new FakeHomeRepository(List.of());
String packageName = "pkg";
String expectedUrl = "https://play.google.com/store/apps/details?id=" + packageName;
repo.setAppUrl(packageName, expectedUrl);
HomeViewModel viewModel = createViewModel(repo);

Intent intent = viewModel.getPromotedAppIntent(packageName);

assertEquals(Intent.ACTION_VIEW, intent.getAction());
assertEquals(Uri.parse(expectedUrl), intent.getData());
}

@Test
public void getLearnMoreIntent_targetsAndroidDevelopers() {
FakeHomeRepository repo = new FakeHomeRepository(List.of());
HomeViewModel viewModel = createViewModel(repo);

Intent intent = viewModel.getLearnMoreIntent();

assertEquals(Intent.ACTION_VIEW, intent.getAction());
assertEquals(Uri.parse("https://developer.android.com"), intent.getData());
}

private HomeViewModel createViewModel(FakeHomeRepository repo) {
return new HomeViewModel(
new GetDailyTipUseCase(repo),
new GetPromotedAppsUseCase(repo),
new GetPlayStoreUrlUseCase(repo),
new GetAppPlayStoreUrlUseCase(repo)
);
}

private static final class FakeHomeRepository implements HomeRepository {
private final List<PromotedApp> promotedApps;
private String dailyTip = "tip";
private String playStoreUrl = "https://play.google.com/store/apps/details?id=default";
private final Map<String, String> appUrls = new HashMap<>();

FakeHomeRepository(List<PromotedApp> promotedApps) {
this.promotedApps = new ArrayList<>(promotedApps);
}

void setDailyTip(String dailyTip) {
this.dailyTip = dailyTip;
}

void setPlayStoreUrl(String playStoreUrl) {
this.playStoreUrl = playStoreUrl;
}

void setAppUrl(String packageName, String url) {
appUrls.put(packageName, url);
}

@Override
public String dailyTip() {
return "tip";
return dailyTip;
}

@Override
public String getPlayStoreUrl() {
return "";
return playStoreUrl;
}

@Override
public String getAppPlayStoreUrl(String packageName) {
return "";
return appUrls.getOrDefault(packageName, "");
}

@Override
public void fetchPromotedApps(PromotedAppsCallback callback) {
callback.onResult(apps);
callback.onResult(promotedApps);
}
}
}
Loading
Loading