Skip to content

Commit

Permalink
Closes mozilla-mobile#5315 - Create a Top Sites storage component
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielluong committed Dec 18, 2019
1 parent 5856d8a commit 6bf7911
Show file tree
Hide file tree
Showing 16 changed files with 566 additions and 3 deletions.
4 changes: 4 additions & 0 deletions .buildconfig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ projects:
path: components/feature/toolbar
description: 'Feature implementation connecting a toolbar implementation with the session module.'
publish: true
feature-top-sites:
path: components/feature/top-sites
description: 'Feature implementation for saving, restoring and organizing top sites.'
publish: true
feature-downloads:
path: components/feature/downloads
description: 'Feature implementation for apps that want to use Android downloads manager.'
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ _Combined components to implement feature-specific use cases._

* 🔴 [**Toolbar**](components/feature/toolbar/README.md) - A component that connects a (concept) toolbar implementation with the browser session module.

* 🔴 [**Top Sites**](components/feature/top-sites/README.md) - Feature implementation for saving, restoring and organizing top sites.

*[**Prompts**](components/feature/prompts/README.md) - A component that will handle all the common prompt dialogs from web content.

*[**Push**](components/feature/push/README.md) - A component that provides Autopush messages with help from a supported push service.
Expand Down Expand Up @@ -268,7 +270,7 @@ _Sample apps using various components._

* [**Nearby Chat**](samples/nearby-chat) - An app demoing how to use the [**Nearby**](components/lib/nearby/README.md) library for peer-to-peer communication between devices.

* [**Toolbar**](samples/toolbar) - An app demoing multiple customized toolbars using the [**browser-toolbar**](components/browser/toolbar/README.md) component.
* [**Toolbar**](samples/toolbar) - An app demoing multiple customized toolbars using the [**browser-toolbar**](components/browser/toolbar/README.md) component.

# Building #

Expand All @@ -282,11 +284,11 @@ $ ./gradlew assemble

## Android Studio ##

If the environment variable `JAVA_HOME` is not defined, you will need to set it. If you would like to use the JDK installed by Android Studio, here's how to find it:
If the environment variable `JAVA_HOME` is not defined, you will need to set it. If you would like to use the JDK installed by Android Studio, here's how to find it:

1. Open Android Studio.
2. Select "Configure".
3. Select "Default Project Structure". You should now see the Android JDK location.
3. Select "Default Project Structure". You should now see the Android JDK location.
4. Set the environment variable `JAVA_HOME` to the location. (How you set an environment variable depends on your OS.)
5. Restart Android Studio.

Expand Down
19 changes: 19 additions & 0 deletions components/feature/top-sites/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# [Android Components](../../../README.md) > Feature > Top Sites

Feature implementation for saving, restoring and organizing top sites.

## Usage

### Setting up the dependency

Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)):

```Groovy
implementation "org.mozilla.components:feature-top-sites:{latest-version}"
```

## License

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/
76 changes: 76 additions & 0 deletions components/feature/top-sites/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
compileSdkVersion config.compileSdkVersion

defaultConfig {
minSdkVersion config.minSdkVersion
targetSdkVersion config.targetSdkVersion
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

packagingOptions {
exclude 'META-INF/proguard/androidx-annotations.pro'
}

sourceSets {
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
}
}

dependencies {
implementation project(':concept-engine')

implementation project(':browser-session')

implementation project(':support-ktx')
implementation project(':support-base')

implementation Dependencies.kotlin_stdlib
implementation Dependencies.kotlin_coroutines

implementation Dependencies.androidx_paging
implementation Dependencies.androidx_lifecycle_extensions
kapt Dependencies.androidx_lifecycle_compiler

implementation Dependencies.androidx_room_runtime
kapt Dependencies.androidx_room_compiler

testImplementation project(':support-test')

testImplementation Dependencies.androidx_test_core
testImplementation Dependencies.testing_junit
testImplementation Dependencies.testing_mockito
testImplementation Dependencies.testing_robolectric
testImplementation Dependencies.kotlin_coroutines

androidTestImplementation project(':support-android-test')

androidTestImplementation Dependencies.androidx_room_testing
androidTestImplementation Dependencies.androidx_arch_core_testing
androidTestImplementation Dependencies.androidx_test_core
androidTestImplementation Dependencies.androidx_test_runner
androidTestImplementation Dependencies.androidx_test_rules
}

apply from: '../../../publish.gradle'
ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description)
21 changes: 21 additions & 0 deletions components/feature/top-sites/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "ce733d9c47cd10312a1c13de8efb7e8d",
"entities": [
{
"tableName": "top_sites",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `url` TEXT NOT NULL, `created_at` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "createdAt",
"columnName": "created_at",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ce733d9c47cd10312a1c13de8efb7e8d')"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package mozilla.components.feature.top.sites

import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.paging.PagedList
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import mozilla.components.feature.top.sites.db.TopSiteDatabase
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNotNull
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

@Suppress("LargeClass") // Large test is large
class TopSiteStorageTest {
private lateinit var context: Context
private lateinit var storage: TopSiteStorage
private lateinit var executor: ExecutorService

@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()

@Before
fun setUp() {
executor = Executors.newSingleThreadExecutor()

context = ApplicationProvider.getApplicationContext()
val database = Room.inMemoryDatabaseBuilder(context, TopSiteDatabase::class.java).build()

storage = TopSiteStorage(context)
storage.database = lazy { database }
}

@After
fun tearDown() {
executor.shutdown()
}

@Test
fun testAddingTopSite() {
storage.addTopSite("Mozilla","https://www.mozilla.org")
}

private fun getAllTopSites(): List<TopSite> {
val dataSource = storage.getTopSitesPaged().create()

val pagedList = PagedList.Builder(dataSource, 10)
.setNotifyExecutor(executor)
.setFetchExecutor(executor)
.build()

return pagedList.toList()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package mozilla.components.feature.top.sites.db

import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.paging.PagedList
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class TopSiteDaoTest {
private val context: Context
get() = ApplicationProvider.getApplicationContext()

private lateinit var database: TopSiteDatabase
private lateinit var topSiteDao: TopSiteDao
private lateinit var executor: ExecutorService

@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()

@Before
fun setUp() {
database = Room.inMemoryDatabaseBuilder(context, TopSiteDatabase::class.java).build()
topSiteDao = database.topSiteDao()
executor = Executors.newSingleThreadExecutor()
}

@After
fun tearDown() {
database.close()
executor.shutdown()
}

@Test
fun testAddingTopSite() {
val topSite = TopSiteEntity(
title = "Mozilla",
url = "https://www.mozilla.org",
createdAt = 200
).also {
it.id = topSiteDao.insertTopSite(it)
}

val dataSource = topSiteDao.getTopSitesPaged().create()

val pagedList = PagedList.Builder(dataSource, 10)
.setNotifyExecutor(executor)
.setFetchExecutor(executor)
.build()

assertEquals(1, pagedList.size)
assertEquals(topSite, pagedList[0]!!)
}

@Test
fun testRemovingTopSite() {
val topSite1 = TopSiteEntity(
title = "Mozilla",
url = "https://www.mozilla.org",
createdAt = 200
).also {
it.id = topSiteDao.insertTopSite(it)
}

val topSite2 = TopSiteEntity(
title = "Firefox",
url = "https://www.firefox.com",
createdAt = 100
).also {
it.id = topSiteDao.insertTopSite(it)
}

topSiteDao.deleteTopSite(topSite1)

val dataSource = topSiteDao.getTopSitesPaged().create()

val pagedList = PagedList.Builder(dataSource, 10)
.setNotifyExecutor(executor)
.setFetchExecutor(executor)
.build()

assertEquals(1, pagedList.size)
assertEquals(topSite2, pagedList[0])
}
}
5 changes: 5 additions & 0 deletions components/feature/top-sites/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="mozilla.components.feature.top.sites" />
Loading

0 comments on commit 6bf7911

Please sign in to comment.