diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..e682dcb8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Built application files +/*/build/ +# Crashlytics configuations +com_crashlytics_export_strings.xml +# Local configuration file (sdk path, etc) +local.properties +# Gradle generated files +.gradle/ +# Signing files +.signing/ +*.apk +# User-specific configurations +.idea/ +.idea/codeStyles +*.iml +# OS-specific files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +build/ +app/google-services.json +/.project diff --git a/Gemfile b/Gemfile new file mode 100755 index 00000000..7a118b49 --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem "fastlane" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..ca1fe147 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,159 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.0) + addressable (2.6.0) + public_suffix (>= 2.0.2, < 4.0) + atomos (0.1.3) + babosa (1.0.2) + claide (1.0.2) + colored (1.2) + colored2 (3.1.2) + commander-fastlane (4.4.6) + highline (~> 1.7.2) + declarative (0.0.10) + declarative-option (0.1.0) + digest-crc (0.4.1) + domain_name (0.5.20180417) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.6.0) + emoji_regex (1.0.1) + excon (0.62.0) + faraday (0.15.4) + multipart-post (>= 1.2, < 3) + faraday-cookie_jar (0.0.6) + faraday (>= 0.7.4) + http-cookie (~> 1.0.0) + faraday_middleware (0.12.2) + faraday (>= 0.7.4, < 1.0) + fastimage (2.1.5) + fastlane (2.114.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.3, < 3.0.0) + babosa (>= 1.0.2, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored + commander-fastlane (>= 4.4.6, < 5.0.0) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 2.0) + excon (>= 0.45.0, < 1.0.0) + faraday (~> 0.9) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 0.9) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-api-client (>= 0.21.2, < 0.24.0) + google-cloud-storage (>= 1.15.0, < 2.0.0) + highline (>= 1.7.2, < 2.0.0) + json (< 3.0.0) + mini_magick (~> 4.5.1) + multi_json + multi_xml (~> 0.5) + multipart-post (~> 2.0.0) + plist (>= 3.1.0, < 4.0.0) + public_suffix (~> 2.0.0) + rubyzip (>= 1.2.2, < 2.0.0) + security (= 0.1.3) + simctl (~> 1.6.3) + slack-notifier (>= 2.0.0, < 3.0.0) + terminal-notifier (>= 1.6.2, < 2.0.0) + terminal-table (>= 1.4.5, < 2.0.0) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.6.0, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3) + gh_inspector (1.1.3) + google-api-client (0.23.9) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.5, < 0.7.0) + httpclient (>= 2.8.1, < 3.0) + mime-types (~> 3.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.0) + signet (~> 0.9) + google-cloud-core (1.2.7) + google-cloud-env (~> 1.0) + google-cloud-env (1.0.5) + faraday (~> 0.11) + google-cloud-storage (1.15.0) + digest-crc (~> 0.4) + google-api-client (~> 0.23) + google-cloud-core (~> 1.2) + googleauth (~> 0.6.2) + googleauth (0.6.7) + faraday (~> 0.12) + jwt (>= 1.4, < 3.0) + memoist (~> 0.16) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (~> 0.7) + highline (1.7.10) + http-cookie (1.0.3) + domain_name (~> 0.5) + httpclient (2.8.3) + json (2.1.0) + jwt (2.1.0) + memoist (0.16.0) + mime-types (3.2.2) + mime-types-data (~> 3.2015) + mime-types-data (3.2018.0812) + mini_magick (4.5.1) + multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) + nanaimo (0.2.6) + naturally (2.2.0) + os (1.0.0) + plist (3.5.0) + public_suffix (2.0.5) + representable (3.0.4) + declarative (< 0.1.0) + declarative-option (< 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rouge (2.0.7) + rubyzip (1.2.2) + security (0.1.3) + signet (0.11.0) + addressable (~> 2.3) + faraday (~> 0.9) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.5) + CFPropertyList + naturally + slack-notifier (2.3.2) + terminal-notifier (1.8.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + tty-cursor (0.6.0) + tty-screen (0.6.5) + tty-spinner (0.9.0) + tty-cursor (~> 0.6.0) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.5) + unicode-display_width (1.4.1) + word_wrap (1.0.0) + xcodeproj (1.7.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.6) + xcpretty (0.3.0) + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.0) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + ruby + +DEPENDENCIES + fastlane + +BUNDLED WITH + 2.0.1 diff --git a/JenkinsUtils.groovy b/JenkinsUtils.groovy new file mode 100644 index 00000000..05fb4e9e --- /dev/null +++ b/JenkinsUtils.groovy @@ -0,0 +1,230 @@ +import groovy.json.JsonOutput + +class Constants { + final static String FALLBACK = 'Required plain-text summary of the attachment.' + final static String COLOR_JOB_SUCCESS = '#36a64f' + final static String COLOR_JOB_FAIL = '#ff0000' + final static String PRETEXT = '' + final static String JOB_NAME = "JOB_NAME" + final static String JOB_LINK = "JOB_URL" + final static String AUTHOR_ICON = 'https://avatars0.githubusercontent.com/u/10986514?v=3&s=400' + final static String APPLICATION_NAME = 'Job executado' + final static String APPLICATION_LINK = "BUILD_URL" + final static String TITLE_JOB_FAIL_SLACK = 'BUILD DEV FAIL' + final static String IMAGE_FAIL_URL = 'http://i.giphy.com/Nweu3IeBIZIvm.gif' + final static String IMAGE_SUCCESS_URL = 'http://i.giphy.com/IO5cB3RVPeklW.gif' + final static String TITLE_JOB_SUCCESS_SLACK = 'BUILD DEV SUCCESS' + final static String TS = '' +} + +class Attachment { + def fallback = Constants.FALLBACK + def color = "#ff0000" + def author_name = "JOB_NAME" + def author_link = "JOB_URL" + def author_icon = Constants.AUTHOR_ICON + def title = Constants.APPLICATION_NAME + def title_link = "BUILD_URL" + def footer = 'Status build success or failed' + def footer_icon = 'Icon URL of the success or failed' + def text = "Stage Build" + def ts = Constants.TS + + Attachment(String color, String jobName, String jobUrl, String buildUrl, String statusSuccessFailed, String stage, String iconSuccessFailed) { + this.color = color + this.author_name = jobName + this.author_link = jobUrl + this.title_link = buildUrl + this.footer = statusSuccessFailed + this.text = stage + this.footer_icon = iconSuccessFailed + } +} + +def notifySlack(String color, String jobName, String jobUrl, String buildUrl, String messengerStatus, String stage, String imageJenkins) { + def slackURL = 'https://hooks.slack.com/services/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' + def payload = JsonOutput.toJson([attachments: [new Attachment(color, jobName, jobUrl, buildUrl, messengerStatus, stage, imageJenkins)]]) + sh "curl -X POST --data-urlencode \'payload=${payload}\' ${slackURL}" +} + +def sendFailedNotify(String messageBuild , Throwable err) { + + notifySlack(Constants.COLOR_JOB_FAIL, + "${env.JOB_NAME}", + "${env.JOB_URL}", + "${env.BUILD_URL}", + "Failed", + "${messageBuild} :broken_heart:", + Constants.IMAGE_FAIL_URL) + + println err.getMessage() + currentBuild.result = "FAILURE" + throw new Exception(messageBuild) +} + +def sendSucessNotify(String messageBuild) { + if (currentBuild.result == "FAILURE") { + echo 'Build Failed' + } else if (currentBuild.result == "UNSTABLE") { + echo 'Build Unstable' + } else { + notifySlack(Constants.COLOR_JOB_SUCCESS, + "${env.JOB_NAME}", + "${env.JOB_URL}", + "${env.BUILD_URL}", + "Success", + "${messageBuild} :heart:", + Constants.IMAGE_SUCCESS_URL) + } +} + +def archivesProject(String pathArchive) { + archiveArtifacts "${pathArchive}" +} + +def archiveXML(String pathXML) { + junit "$pathXML/*.xml" +} + +def publishHtmlProject(String pathPublish, String namePublish) { + publishHTML([allowMissing: true, + alwaysLinkToLastBuild: true, + keepAll: true, + reportDir: "${pathPublish}", + reportFiles: 'index.html', + reportName: "${namePublish}", + reportTitles: '']) +} + +def upgradeVersionName() { + sh ''' + BUILD_VERSION=$(cat tools/version/version_code.txt) + VERSION_NEW="$BUILD_VERSION"."$BUILD_NUMBER" + echo $VERSION_NEW | tr -d "\n" > tools/version/version_name.txt + cat tools/version/version_name.txt + ''' +} + +def testsKtlint() { + try { + sh """ + java -version + ./gradlew wrapper + ./gradlew ktlint + """ + publishHtmlProject('app/build/reports/ktlint/', 'Ktlint') + } catch (err) { + publishHtmlProject('app/build/reports/ktlint/', 'Ktlint') + sendFailedNotify('ktlint Tests', err) + } +} + +def lintDebug() { + try { + // padrao nome de JOB: xx-xx-xx/xx-xx-xx-xx-xx/PR- + def bitbucketID = env.JOB_NAME.split('-')[7] + sh "./gradlew lintDebug" + sh "./gradlew addCommentsForPR -DpullRequestId=${bitbucketID}" + publishHtmlProject('app/build/reports/lint/', 'Lint Debug') + } catch(err) { + publishHtmlProject('app/build/reports/lint/', 'Lint Debug') + sendFailedNotify('Lint Debug', err) + } +} + +def buildApk(String buildType) { + try { + def lowercaseBuidtype = buildType.toLowerCase() + sh "./gradlew :app:assemble${buildType} --stacktrace --info --profile" + archivesProject("app/build/outputs/apk/${lowercaseBuidtype}/app-${lowercaseBuidtype}.apk") + } catch(err) { + sendFailedNotify('Build APK', err) + } +} + +def buildAPkRelease(){ + try{ + sh ''' + ./gradlew assemble --stacktrace --info --profile + /Library/Java/AndroidSDK/build-tools/28.0.3/zipalign -v -p 4 app/build/outputs/apk/release/app-release-unsigned.apk app/build/outputs/apk/release/app-release-unsigned-aligned.apk + /Library/Java/AndroidSDK/build-tools/28.0.3/apksigner sign -ks /Users/Shared/Jenkins/Home/tentacleFiles/assinaturaApp/tentacle_keystore.jks --ks-key-alias Tentacle --ks-pass file:/Users/Shared/Jenkins/Home/tentacleFiles/assinaturaApp/key_pass --key-pass file:/Users/Shared/Jenkins/Home/tentacleFiles/assinaturaApp/alias_pass --out tentacle-release.apk app/build/outputs/apk/release/app-release-unsigned-aligned.apk + ''' + archivesProject("app/build/outputs/apk/release/app-release-unsigned-aligned.apk") + }catch(err) { + sendFailedNotify('Build APK Release', err) + } + +} + +def unitTests(String buildType) { + try { + sh "./gradlew test${buildType}UnitTest" + archiveXML("app/build/test-results/test${buildType}UnitTest") + publishHtmlProject("app/build/reports/tests/test${buildType}UnitTest", 'Local Tests') + } catch (err) { + publishHtmlProject("app/build/reports/tests/test${buildType}UnitTest", 'Local Tests') + sendFailedNotify('Local Tests', err) + } +} + +def killEmulator() { + sh ''' + /Users/macmini-recife/homebrew/bin/adb devices -l |grep emulator-5554 + if [[ $? -eq 0 ]]; then + PROCESS=$(ps -ef |grep -v grep |grep Nexus5XAPI26 |awk '{print $2}') + kill -9 ${PROCESS} + + sleep 5 + fi + ''' +} + +def instrumentTests() { + try { + sh ''' + /Library/Java/AndroidSDK/emulator/emulator -avd Nexus5XAPI26 -netdelay none -netspeed full & + sleep 120 + + ./gradlew uninstallAll + ./gradlew connectedDebugAndroidTest + ''' + killEmulator() + publishHtmlProject('app/build/reports/androidTests/connected', 'Instrument Tests') + archivesProject("app/build/reports/androidTests/connected/index.html") + } + catch(err) { + killEmulator() + publishHtmlProject('app/build/reports/androidTests/connected', 'Instrument Tests') + archivesProject("app/build/reports/androidTests/connected/index.html") + sendFailedNotify('Instrument Tests', err) + } +} + +def reportJacoco() { + try { + sh "./gradlew jacocoReport" + publishHtmlProject('app/build/reports/jacoco/jacocoReport/html/', 'Code Coverage') + } + catch(err) { + publishHtmlProject('app/build/reports/jacoco/jacocoReport/html/', 'Code Coverage') + sendFailedNotify('Report Jacoco', err) + } +} + +def releaseAndroidAPKToCrashlytics(String buildType) { + try { + sh "./gradlew :app:crashlyticsUploadDistribution${buildType}" + } catch(err) { + sendFailedNotify('Release Crashlytics', err) + } +} + +def gradleClean() { + sh "./gradlew clean" +} + +def cpArquivos() { + sh "cp /Users/Shared/Jenkins/Home/tentacleFiles/jsonFirebaseTentacle/google-services.json /Users/Shared/Jenkins/Home/workspace/tentacle-frontend-android-release-build/app" +} + +return this diff --git a/JenkinsfileTentacleDevelop.groovy b/JenkinsfileTentacleDevelop.groovy new file mode 100644 index 00000000..45df23c6 --- /dev/null +++ b/JenkinsfileTentacleDevelop.groovy @@ -0,0 +1,36 @@ +#!groovy +node('master') { + + println "\u2756 ${env.JOB_NAME} \u2756" + + stage('Checkout') { + deleteDir() + checkout scm + } + + def utils = load('JenkinsUtils.groovy') + + stage('cp Arquivos') { + utils.cpArquivos() + } + + stage('clean') { + utils.gradleClean() + } + + /*stage('Version') { + utils.upgradeVersionName() + }*/ + + stage('Build APK') { + utils.buildApk('Debug') + } + + /*stage('Release') { + utils.releaseAndroidAPKToCrashlytics('Debug') + }*/ + + stage('Inform Build OK') { + utils.sendSucessNotify('Job success') + } +} diff --git a/JenkinsfileTentaclePR.groovy b/JenkinsfileTentaclePR.groovy new file mode 100644 index 00000000..5d9d33fa --- /dev/null +++ b/JenkinsfileTentaclePR.groovy @@ -0,0 +1,53 @@ +#!groovy +node('master') { + + println "\u2756 ${env.JOB_NAME} \u2756" + + stage('Checkout') { + deleteDir() + checkout scm + + } + + def utils = load('JenkinsUtils.groovy') + + stage('cp Arquivos') { + utils.cpArquivoFirebaseJson() + } + + stage('clean') { + utils.gradleClean() + } + + /*stage('Version') { + utils.upgradeVersionName() + }*/ + + stage('Sintaxe Code') { + utils.testsKtlint() + } + + stage('Lint Debug') { + utils.lintDebug() + } + + stage('Build APK') { + utils.buildApk('Debug') + } + + stage('Unit Tests') { + utils.unitTests('Debug') + } + + stage('Instruments Tests') { + utils.instrumentTests() + } + + stage('Jacoco Report') { + utils.reportJacoco() + } + + stage('Inform Build OK') { + utils.sendSucessNotify('Job success') + } +} diff --git a/JenkinsfileTentacleRelease.groovy b/JenkinsfileTentacleRelease.groovy new file mode 100644 index 00000000..7425c0c3 --- /dev/null +++ b/JenkinsfileTentacleRelease.groovy @@ -0,0 +1,36 @@ +#!groovy +node('master') { + + println "\u2756 ${env.JOB_NAME} \u2756" + + stage('Checkout') { + deleteDir() + checkout scm + } + + def utils = load('JenkinsUtils.groovy') + + stage('cp Arquivos') { + utils.cpArquivos() + } + + stage('clean') { + utils.gradleClean() + } + + /*stage('Version') { + utils.upgradeVersionName() + }*/ + + stage('Build APK') { + utils.buildApk('Release') + } + + /*stage('Release') { + utils.releaseAndroidAPKToCrashlytics('Release') + }*/ + + stage('Inform Build OK') { + utils.sendSucessNotify('Job success') + } +} diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 00000000..0ca0f3e7 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,174 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: "de.mannodermaus.android-junit5" + +apply plugin: 'kotlin-allopen' + +apply plugin: 'kotlin-kapt' + +apply from: 'tasks.gradle' + +apply plugin: 'io.fabric' + +apply plugin: 'jacoco' + +apply plugin: 'androidx.navigation.safeargs' + +allOpen { + // allows mocking for classes w/o directly opening them for release builds + annotation 'br.com.concrete.tentacle.testing.OpenClass' +} + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "br.com.concrete.tentacle" + minSdkVersion 21 + targetSdkVersion 28 + versionCode 106 + versionName "1.0.6" + testInstrumentationRunner "br.com.concrete.tentacle.util.TentacleTestRunner" + } + buildTypes { + debug { + buildConfigField "String", "BASE_URL", '"https://tentacle-backend-dev.herokuapp.com/"' + applicationIdSuffix ".debug" + testCoverageEnabled true + } + + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + buildConfigField "String", "BASE_URL", '"https://tentacle-backend.herokuapp.com/"' + } + } + + testOptions { + unitTests { + includeAndroidResources = true + returnDefaultValues = true + all { + jacoco { + includeNoLocationClasses = true + } + } + } + } + + sourceSets.test.resources.srcDirs += ["src/debug/assets"] +} + +androidExtensions { + experimental = true +} + +configurations { + ktlint +} + +jacoco { + toolVersion = "$jacobVersion" +} + +tasks.withType(Test) { + jacoco.includeNoLocationClasses = true +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" + implementation "com.google.android.material:material:$material" + implementation "androidx.appcompat:appcompat:$appCompat" + implementation "androidx.constraintlayout:constraintlayout:$constraitLayout" + + //UI Components + //https://github.com/MdFarhanRaja/SearchableSpinner + implementation "com.github.MdFarhanRaja:SearchableSpinner:$searchableSpinner" + + //firebase + implementation "com.google.firebase:firebase-core:$firebaseCore" + implementation "com.google.firebase:firebase-messaging:$firebaseMessaging" + implementation "com.google.firebase:firebase-iid:$firebaseIid" + implementation "com.firebase:firebase-jobdispatcher:$firebaseDispatcher" + + //Test + implementation "androidx.legacy:legacy-support-v4:$legacySupport" + implementation "androidx.recyclerview:recyclerview:$legacySupport" + testImplementation "junit:junit:$junit" + testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$junit5" + androidTestImplementation "androidx.test:runner:$runner" + androidTestImplementation "androidx.test:rules:$androidxTest" + androidTestImplementation "androidx.test.espresso:espresso-core:$expresso" + testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5" + testImplementation "org.robolectric:robolectric:$robolectric" + testImplementation "android.arch.core:core-testing:$coreTesting" + testImplementation "com.squareup.okhttp3:mockwebserver:$okhttp3" + androidTestImplementation "com.squareup.okhttp3:mockwebserver:$okhttp3" + androidTestImplementation "org.mockito:mockito-android:$mockitoAndroid" + androidTestImplementation "androidx.test.ext:junit:$androidxTest" + androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoIntent" + androidTestImplementation("com.android.support.test.espresso:espresso-contrib:$espressoContrib") { + exclude group: 'com.android.support', module: 'appcompat' + exclude group: 'com.android.support', module: 'support-v4' + exclude group: 'com.android.support', module: 'support-annotations' + exclude module: 'recyclerview-v7' + } + + //Koin + implementation "org.koin:koin-core:$koinVersion" + implementation "org.koin:koin-android:$koinVersion" + implementation "org.koin:koin-android-viewmodel:$koinVersion" + testImplementation "org.koin:koin-test:$koinVersion" + + //Retrofit + implementation "com.squareup.retrofit2:retrofit:$retrofitVersion" + implementation "com.squareup.retrofit2:converter-gson:$retrofitVersion" + implementation "com.squareup.okhttp3:logging-interceptor:$retrofitLogging" + implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofitAdapterRxJava" + implementation "com.squareup.okhttp3:okhttp:$okhttp3" + + //Observable + implementation "io.reactivex.rxjava2:rxandroid:$rxAndroid" + implementation "io.reactivex.rxjava2:rxjava:$rxJava" + + //AndroidX ViewModel/LiveData + implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle" + implementation "com.google.android.material:material:$androidMaterial" + + //Utils + implementation "br.com.concrete:canarinho:$canarinho" + + //Navigation + implementation "android.arch.navigation:navigation-fragment-ktx:$navigation" + implementation "android.arch.navigation:navigation-ui-ktx:$navigation" + + implementation("com.crashlytics.sdk.android:crashlytics:$crashlyticsVersion@aar") { + transitive = true + } + + //Glide + implementation "com.github.bumptech.glide:glide:$glide" + kapt "com.github.bumptech.glide:compiler:$glide" + + ktlint "com.github.shyiko:ktlint:$ktLintVersion" + implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinReflection" + + //https://github.com/jaredrummler/MaterialSpinner + implementation "com.jaredrummler:material-spinner:$materialSpinner" + + //PinchToZoom + implementation "com.github.chrisbanes:PhotoView:$pinchZoom" + + //takePicture + implementation 'com.github.jkwiecien:EasyImage:1.3.1' + + implementation 'com.github.santalu:auto-viewpager:1.0.8' +} + +// Add to the bottom of the file +apply plugin: 'com.google.gms.google-services' diff --git a/app/com.crashlytics.settings.json b/app/com.crashlytics.settings.json new file mode 100644 index 00000000..2eef0da6 --- /dev/null +++ b/app/com.crashlytics.settings.json @@ -0,0 +1 @@ +{"settings_version":2,"cache_duration":60,"features":{"collect_logged_exceptions":true,"collect_reports":true,"collect_analytics":false,"prompt_enabled":false,"push_enabled":true,"firebase_crashlytics_enabled":false},"analytics":{"url":"https:\/\/e.crashlytics.com\/spi\/v2\/events","flush_interval_secs":600,"max_file_count_per_send":1,"track_custom_events":true,"track_predefined_events":true,"track_view_controllers":false,"flush_on_background":true,"max_byte_size_per_file":8000,"max_pending_send_file_count":100,"sampling_rate":1,"forward_to_google_analytics":false,"include_purchase_events_in_forwarded_events":false},"beta":{"update_suspend_duration":1209600,"update_endpoint":""},"app":{"identifier":"br.com.concrete.tentacle","status":"activated","url":"https:\/\/api.crashlytics.com\/spi\/v1\/platforms\/android\/apps\/br.com.concrete.tentacle","reports_url":"https:\/\/reports.crashlytics.com\/spi\/v1\/platforms\/android\/apps\/br.com.concrete.tentacle\/reports","ndk_reports_url":"https:\/\/reports.crashlytics.com\/sdk-api\/v1\/platforms\/android\/apps\/br.com.concrete.tentacle\/minidumps","update_required":true},"session":{"log_buffer_size":64000,"max_chained_exception_depth":16,"max_complete_sessions_count":4,"max_custom_exception_events":8,"max_custom_key_value_pairs":64,"identifier_mask":255},"prompt":{"title":"Send Crash Report?","message":"Looks like we crashed! Please help us fix the problem by sending a crash report.","send_button_title":"Send","show_cancel_button":true,"cancel_button_title":"Don't Send","show_always_send_button":true,"always_send_button_title":"Always Send"},"expires_at":1549394090939} \ No newline at end of file diff --git a/app/fabric.properties b/app/fabric.properties new file mode 100644 index 00000000..ef57d1fc --- /dev/null +++ b/app/fabric.properties @@ -0,0 +1,3 @@ +#Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public. +#Mon Jan 21 14:49:31 GMT 2019 +apiSecret=ca348cd580e068f0ee2feb5a8cf76d516381b4a7f23ba9efb952ffba23dc98a2 diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 00000000..2f83d943 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,32 @@ +# 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 + +#Glide +-keep public class * implements com.bumptech.glide.module.GlideModule +-keep public class * extends com.bumptech.glide.module.AppGlideModule +-keep public enum com.bumptech.glide.load.ImageHeaderParser$** { + **[] $VALUES; + public *; +} + +# for DexGuard only +-keepresourcexmlelements manifest/application/meta-data@value=GlideModule \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/TentacleTestApp.kt b/app/src/androidTest/java/br/com/concrete/tentacle/TentacleTestApp.kt new file mode 100644 index 00000000..5994cae4 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/TentacleTestApp.kt @@ -0,0 +1,35 @@ +package br.com.concrete.tentacle + +import android.app.Application +import android.os.AsyncTask +import br.com.concrete.tentacle.di.PROPERTY_BASE_URL +import br.com.concrete.tentacle.di.androidModule +import br.com.concrete.tentacle.di.eventsModule +import br.com.concrete.tentacle.di.networkModule +import br.com.concrete.tentacle.di.repositoryModule +import br.com.concrete.tentacle.di.viewModelModule +import io.reactivex.plugins.RxJavaPlugins +import io.reactivex.schedulers.Schedulers +import org.koin.android.ext.android.startKoin + +private const val LOCALHOST_URL = "http://localhost:8080/" + +class TentacleTestApp : Application() { + + override fun onCreate() { + super.onCreate() + + RxJavaPlugins.setInitComputationSchedulerHandler { Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR) } + RxJavaPlugins.setInitIoSchedulerHandler { Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR) } + + startKoin(this, + listOf(androidModule, + networkModule, + viewModelModule, + repositoryModule, + eventsModule + ), + + extraProperties = mapOf(PROPERTY_BASE_URL to LOCALHOST_URL)) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/actions/SetTextInTextView.kt b/app/src/androidTest/java/br/com/concrete/tentacle/actions/SetTextInTextView.kt new file mode 100644 index 00000000..b1f7ef21 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/actions/SetTextInTextView.kt @@ -0,0 +1,22 @@ +package br.com.concrete.tentacle.actions + +import android.view.View +import android.widget.TextView +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom +import org.hamcrest.Matcher + +class SetTextInTextView(private val text: String) : ViewAction { + override fun getDescription(): String { + return "Set text in TextView" + } + + override fun getConstraints(): Matcher { + return isAssignableFrom(TextView::class.java) + } + + override fun perform(uiController: UiController?, view: View?) { + (view as TextView).text = text + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/base/BaseFragmentNoActionBarNoBottomBarTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/base/BaseFragmentNoActionBarNoBottomBarTest.kt new file mode 100644 index 00000000..b0c22cf2 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/base/BaseFragmentNoActionBarNoBottomBarTest.kt @@ -0,0 +1,100 @@ +package br.com.concrete.tentacle.base + +import android.app.Activity +import android.app.Instrumentation +import androidx.navigation.NavHost +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.rule.ActivityTestRule +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.childAtPosition +import br.com.concrete.tentacle.testing.SingleFragmentTestActivityNoActionBarNoBottomBar +import org.hamcrest.CoreMatchers +import org.hamcrest.Matchers +import org.junit.Before +import org.junit.Ignore +import org.junit.Rule +import java.io.File + +@Ignore +abstract class BaseFragmentNoActionBarNoBottomBarTest : BaseInstrumentedTest() { + + companion object { + var intentsInitialized = false + + fun init() { + if (!intentsInitialized) { + Intents.init() + intentsInitialized = true + } + } + } + + @get:Rule + val activityRule = ActivityTestRule(SingleFragmentTestActivityNoActionBarNoBottomBar::class.java) + + abstract fun setupFragment() + + @Before + open fun before() { + clearApplicationData() + setupFragment() + init() + + testFragment.let { + activityRule.activity.setFragment(it) + } + } + + fun setField(textField: String, id: Int) { + onView( + Matchers.allOf( + ViewMatchers.withId(R.id.edt), + ViewMatchers.withId(id) + .childAtPosition(0) + .childAtPosition(1) + ) + ).perform( + ViewActions.scrollTo(), + ViewActions.replaceText(textField) + ) + } + + private fun clearApplicationData() { + val cacheDirectory = activityRule.activity.cacheDir + val applicationDirectory = File(cacheDirectory.parent) + if (applicationDirectory.exists()) { + val fileNames = applicationDirectory.list() + for (fileName in fileNames) { + if (fileName != "lib") { + deleteFile(File(applicationDirectory, fileName)) + } + } + } + } + + private fun deleteFile(file: File?): Boolean { + var deletedAll = true + if (file != null) { + if (file.isDirectory) { + val children = file.list() + for (i in children.indices) { + deletedAll = deleteFile(File(file, children[i])) && deletedAll + } + } else { + deletedAll = file!!.delete() + } + } + + return deletedAll + } + + fun checkIfGoesToHome() { + val matcher = CoreMatchers.allOf(IntentMatchers.hasComponent(NavHost::class.java.name)) + val result = Instrumentation.ActivityResult(Activity.RESULT_OK, null) + Intents.intending(matcher).respondWith(result) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/base/BaseFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/base/BaseFragmentTest.kt new file mode 100644 index 00000000..9d3e94ec --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/base/BaseFragmentTest.kt @@ -0,0 +1,70 @@ +package br.com.concrete.tentacle.base + +import android.Manifest +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions.replaceText +import androidx.test.espresso.action.ViewActions.scrollTo +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.rule.ActivityTestRule +import androidx.test.rule.GrantPermissionRule +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.childAtPosition +import br.com.concrete.tentacle.testing.SingleFragmentTestActivity +import org.hamcrest.Matchers +import org.junit.Before +import org.junit.Ignore +import org.junit.Rule +import org.junit.rules.RuleChain + +@Ignore +abstract class BaseFragmentTest : BaseInstrumentedTest() { + + @get:Rule + val activityRule = ActivityTestRule(SingleFragmentTestActivity::class.java) + + @get:Rule + val screenshotTestRule = ScreenshotTestRule() + + @get:Rule + val screenShotRule = RuleChain + .outerRule(GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)) + .around(ScreenshotTestRule()) + + abstract fun setupFragment() + + @Before + open fun before() { + setupFragment() + + testFragment.let { + activityRule.activity.setFragment(it) + } + } + + fun setField(textField: String, id: Int) { + Espresso.onView( + Matchers.allOf( + withId(R.id.edt), + withId(id) + .childAtPosition(0) + .childAtPosition(1) + ) + ).perform( + scrollTo(), + replaceText(textField) + ) + } + + fun checkInputField(textField: String, id: Int) { + Espresso.onView( + Matchers.allOf( + withId(R.id.edt), + withId(id) + .childAtPosition(0) + .childAtPosition(1) + ) + ).check(matches(withText(textField))) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/base/BaseInstrumentedTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/base/BaseInstrumentedTest.kt new file mode 100644 index 00000000..72aa1ee5 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/base/BaseInstrumentedTest.kt @@ -0,0 +1,37 @@ +package br.com.concrete.tentacle.base + +import androidx.fragment.app.Fragment +import androidx.test.ext.junit.runners.AndroidJUnit4 +import br.com.concrete.tentacle.data.repositories.SharedPrefRepositoryContract +import okhttp3.mockwebserver.MockWebServer +import org.junit.After +import org.junit.Before +import org.junit.Ignore +import org.junit.runner.RunWith +import org.koin.standalone.KoinComponent +import org.koin.standalone.inject + +@Ignore +@RunWith(AndroidJUnit4::class) +abstract class BaseInstrumentedTest : KoinComponent { + + private val sharedPrefRepositoryContract: SharedPrefRepositoryContract by inject() + + lateinit var mockWebServer: MockWebServer + lateinit var testFragment: Fragment + + @Before + fun setUp() { + mockWebServer = MockWebServer() + mockWebServer.start(8080) + sharedPrefRepositoryContract.removeSession() + sharedPrefRepositoryContract.removeUser() + } + + @After + fun after() { + mockWebServer.shutdown() + sharedPrefRepositoryContract.removeSession() + sharedPrefRepositoryContract.removeUser() + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/base/ScreenshotTestRule.kt b/app/src/androidTest/java/br/com/concrete/tentacle/base/ScreenshotTestRule.kt new file mode 100644 index 00000000..f3e6b615 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/base/ScreenshotTestRule.kt @@ -0,0 +1,35 @@ +package br.com.concrete.tentacle.base + +import android.graphics.Bitmap +import androidx.test.runner.screenshot.BasicScreenCaptureProcessor +import androidx.test.runner.screenshot.ScreenCaptureProcessor +import androidx.test.runner.screenshot.Screenshot +import org.junit.rules.TestWatcher +import java.io.IOException + +class ScreenshotTestRule : TestWatcher() { + + override fun failed(e: Throwable?, description: org.junit.runner.Description?) { + super.failed(e, description) + + takeScreenShot(description) + } + + private fun takeScreenShot(description: org.junit.runner.Description?) { + description?.let { desc -> + val fileName = "${desc.testClass.simpleName} - $desc" + + val capture = Screenshot.capture() + capture.name = fileName + capture.format = Bitmap.CompressFormat.PNG + val processors = HashSet() + processors.add(BasicScreenCaptureProcessor()) + + try { + capture.process(processors) + } catch (ex: IOException) { + ex.printStackTrace() + } + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/extensions/IntegerExtensions.kt b/app/src/androidTest/java/br/com/concrete/tentacle/extensions/IntegerExtensions.kt new file mode 100644 index 00000000..1b5f6705 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/extensions/IntegerExtensions.kt @@ -0,0 +1,67 @@ +package br.com.concrete.tentacle.extensions + +import android.content.res.Resources +import android.view.View +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import org.hamcrest.Description +import org.hamcrest.TypeSafeMatcher + +fun Int.checkLines(): TypeSafeMatcher { + + var lines = this + return object : TypeSafeMatcher() { + override fun describeTo(description: Description?) { + description?.appendText("IsTextInLines") + } + + override fun matchesSafely(item: View?): Boolean { + return (item as TextView).lineCount == lines + } + } +} + +fun Int.atPositionOnView(position: Int, targetViewId: Int = -1): TypeSafeMatcher { + val recyclerViewId = this + return object : TypeSafeMatcher() { + var resources: Resources? = null + var childView: View? = null + + override fun describeTo(description: Description) { + var idDescription = Integer.toString(recyclerViewId) + if (this.resources != null) { + try { + idDescription = this.resources!!.getResourceName(recyclerViewId) + } catch (var4: Resources.NotFoundException) { + idDescription = String.format( + "%s (resource name not found)", + *arrayOf(Integer.valueOf(recyclerViewId)) + ) + } + } + + description.appendText("with id: $idDescription") + } + + public override fun matchesSafely(view: View): Boolean { + + this.resources = view.resources + + if (childView == null) { + val recyclerView = view.rootView.findViewById(recyclerViewId) as RecyclerView? + if (recyclerView != null && recyclerView.id == recyclerViewId) { + childView = recyclerView.findViewHolderForAdapterPosition(position)!!.itemView + } else { + return false + } + } + + return if (targetViewId == -1) { + view === childView + } else { + val targetView = childView!!.findViewById(targetViewId) + view === targetView + } + } + } +} diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/extensions/MatcherViewExtensions.kt b/app/src/androidTest/java/br/com/concrete/tentacle/extensions/MatcherViewExtensions.kt new file mode 100644 index 00000000..6c58a3d8 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/extensions/MatcherViewExtensions.kt @@ -0,0 +1,61 @@ +package br.com.concrete.tentacle.extensions + +import android.view.View +import android.view.ViewGroup +import androidx.test.espresso.IdlingRegistry +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.matcher.ViewMatchers +import br.com.concrete.tentacle.util.LayoutChangeCallback +import org.hamcrest.Description +import org.hamcrest.Matcher +import org.hamcrest.StringDescription +import org.hamcrest.TypeSafeMatcher + +fun Matcher.waitUntil(): ViewAction { + val matcher = this + return ViewActions.actionWithAssertions(object : ViewAction { + override fun getConstraints(): Matcher { + return ViewMatchers.isAssignableFrom(View::class.java) + } + + override fun getDescription(): String { + val description = StringDescription() + matcher.describeTo(description) + return String.format("wait until: %s", description) + } + + override fun perform(uiController: UiController, view: View) { + if (!matcher.matches(view)) { + val callback = LayoutChangeCallback(matcher) + try { + IdlingRegistry.getInstance().register(callback) + view.addOnLayoutChangeListener(callback) + uiController.loopMainThreadUntilIdle() + } finally { + view.removeOnLayoutChangeListener(callback) + IdlingRegistry.getInstance().unregister(callback) + } + } + } + }) +} + +fun Matcher.childAtPosition( + position: Int +): Matcher { + val parentMatcher = this + return object : TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("Child at position $position in parent ") + parentMatcher.describeTo(description) + } + + public override fun matchesSafely(view: View): Boolean { + val parent = view.parent + return parent is ViewGroup && parentMatcher.matches(parent) && + view == parent.getChildAt(position) + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/extensions/StringExtensions.kt b/app/src/androidTest/java/br/com/concrete/tentacle/extensions/StringExtensions.kt new file mode 100644 index 00000000..163ffcb0 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/extensions/StringExtensions.kt @@ -0,0 +1,8 @@ +package br.com.concrete.tentacle.extensions + +import androidx.test.platform.app.InstrumentationRegistry + +fun String.getJson() = InstrumentationRegistry.getInstrumentation() + .targetContext + .assets + .open(this).bufferedReader().use { it.readText() } \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/HostActivityTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/HostActivityTest.kt new file mode 100644 index 00000000..0c49f2df --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/HostActivityTest.kt @@ -0,0 +1,72 @@ +package br.com.concrete.tentacle.features + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.rule.ActivityTestRule +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.testing.BottomBarTestActivity +import org.hamcrest.core.AllOf.allOf +import org.hamcrest.core.IsNot.not +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class HostActivityTest { + + @get:Rule + var activityTestRule = object : ActivityTestRule(BottomBarTestActivity::class.java) {} + + @Test + fun bottomBarNavigationHome() { + onView(withId(R.id.bottomBar)).check(matches(isDisplayed())) + + selectedView(R.id.action_home, true) + selectedView(R.id.action_library, false) + selectedView(R.id.action_games, false) + selectedView(R.id.action_reservation, false) + } + + @Test + fun bottomBarNavigationLibrary() { + + onView(withId(R.id.action_library)).perform(click()) + + selectedView(R.id.action_home, false) + selectedView(R.id.action_library, true) + selectedView(R.id.action_games, false) + selectedView(R.id.action_reservation, false) + } + + @Test + fun bottomBarNavigationGames() { + + onView(withId(R.id.action_games)).perform(click()) + + selectedView(R.id.action_home, false) + selectedView(R.id.action_library, false) + selectedView(R.id.action_games, true) + selectedView(R.id.action_reservation, false) + } + + @Test + fun bottomBarNavigationReservation() { + + onView(withId(R.id.action_reservation)).perform(click()) + + selectedView(R.id.action_home, false) + selectedView(R.id.action_library, false) + selectedView(R.id.action_games, false) + selectedView(R.id.action_reservation, true) + } + + private fun selectedView(viewId: Int, shouldBeVisible: Boolean) { + val assertion = if (shouldBeVisible) matches(isDisplayed()) else matches(not(isDisplayed())) + onView(allOf(withId(R.id.selectedView), isDescendantOfA(withId(viewId)))).check(assertion) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/filter/FilterDialogFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/filter/FilterDialogFragmentTest.kt new file mode 100644 index 00000000..607e9bde --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/filter/FilterDialogFragmentTest.kt @@ -0,0 +1,119 @@ +package br.com.concrete.tentacle.features.filter + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.extensions.waitUntil +import br.com.concrete.tentacle.features.library.LibraryFragment +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.Matchers.allOf +import org.hamcrest.Matchers.not +import org.junit.Before +import org.junit.Test + +class FilterDialogFragmentTest : BaseFragmentTest() { + + override fun setupFragment() { + testFragment = LibraryFragment() + } + + @Before + fun setFragment() { + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody("mockjson/library/get_library_success.json".getJson())) + onView(withId(R.id.filterMenuId)).perform(click()) + } + + @Test + fun btnClearFilterIsDisplayed() { + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody("mockjson/library/get_library_success.json".getJson())) + onView( + withId(R.id.filterContent) + ).perform(isDisplayed().waitUntil()) + + onView( + allOf( + withText("Playstation 3") + )) + .perform(click()) + + onView(withId(R.id.filterClearButtonView)) + .check(matches(isDisplayed())) + } + + @Test + fun btnClearFilterDisappear() { + onView( + withId(R.id.filterContent) + ).perform(isDisplayed().waitUntil()) + + onView( + allOf( + withText("Playstation 3") + )) + .perform(click()) + + onView(withId(R.id.filterClearButtonView)) + .check(matches(isDisplayed())) + + onView( + allOf( + withText("Playstation 3") + )) + .perform(click()) + + onView(withId(R.id.filterClearButtonView)) + .check(matches(not(isDisplayed()))) + } + + @Test + fun btnClearFilterSuccess() { + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody("mockjson/library/get_library_success.json".getJson())) + onView( + withId(R.id.filterContent) + ).perform(isDisplayed().waitUntil()) + + onView( + allOf( + withText("Playstation 3") + )) + .perform(click()) + + onView( + allOf( + withText("Playstation 4") + )) + .perform(click()) + + onView(withId(R.id.filterClearButtonView)).perform(click()) + onView(withId(R.id.list)).check(matches(isDisplayed())) + } + + @Test + fun btnFilterSuccess() { + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody("mockjson/library/get_library_success.json".getJson())) + onView( + withId(R.id.filterContent) + ).perform(isDisplayed().waitUntil()) + + onView( + allOf( + withText("Playstation 3") + )) + .perform(click()) + + onView( + allOf( + withText("Playstation 4") + )) + .perform(click()) + + onView(withId(R.id.filterButtonView)).perform(click()) + onView(withId(R.id.list)).check(matches(isDisplayed())) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/forgotPassword/passwordRecovery/PasswordRecoveryFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/forgotPassword/passwordRecovery/PasswordRecoveryFragmentTest.kt new file mode 100644 index 00000000..8cff3b8a --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/forgotPassword/passwordRecovery/PasswordRecoveryFragmentTest.kt @@ -0,0 +1,138 @@ +package br.com.concrete.tentacle.features.forgotPassword.passwordRecovery + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.ViewAssertion +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.replaceText +import androidx.test.espresso.action.ViewActions.scrollTo +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.extensions.childAtPosition +import br.com.concrete.tentacle.extensions.getJson +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.Matchers.not +import org.junit.Test + +class PasswordRecoveryFragmentTest : BaseFragmentTest() { + + override fun setupFragment() { + val emailTest = "email@email.com" + testFragment = PasswordRecoveryFragment.newInstance(emailTest) + } + + @Test + fun shouldFillEmailInputFieldWhenHasIntentExtras() { + onView(withId(R.id.emailEditText)) + .check(matches(hasDescendant(withText("email@email.com")))) + } + + @Test + fun shouldShowInputFieldsErrorsWhenNothingIsFilled() { + setInputField(R.id.emailEditText, "") + performClickButton() + + checkErrorById(R.id.emailEditText) { + matches(isDisplayed()) + } + + checkErrorById(R.id.tokenEditText) { + matches(isDisplayed()) + } + + checkErrorById(R.id.newPassEditText) { + matches(isDisplayed()) + } + + checkErrorById(R.id.newPassConfirmationEditText) { + matches(not(isDisplayed())) + } + } + + @Test + fun invalidPassword() { + setInputField(R.id.tokenEditText, "AIU8D") + setInputField(R.id.newPassEditText, "12345") + performClickButton() + + checkErrorById(R.id.newPassEditText) { + matches(isDisplayed()) + } + checkErrorById(R.id.newPassEditText) { + matches(withText("O campo password precisa ter no mínimo 6 digitos")) + } + } + + @Test + fun invalidConfirmationPassword() { + setInputField(R.id.tokenEditText, "AIU8D") + setInputField(R.id.newPassEditText, "123456") + setInputField(R.id.newPassConfirmationEditText, "12345") + performClickButton() + + checkErrorById(R.id.newPassConfirmationEditText) { + matches(isDisplayed()) + } + checkErrorById(R.id.newPassConfirmationEditText) { + matches(withText("O campo password precisa ter no mínimo 6 digitos")) + } + } + + @Test + fun passwordsDoesNotMatch() { + setInputField(R.id.tokenEditText, "AIU8D") + setInputField(R.id.newPassEditText, "123456") + setInputField(R.id.newPassConfirmationEditText, "123457") + performClickButton() + + checkErrorById(R.id.newPassConfirmationEditText) { + matches(isDisplayed()) + } + checkErrorById(R.id.newPassConfirmationEditText) { + matches(withText("Os campos senha e comfirmação de senha não coincidem")) + } + } + + @Test + fun restorePasswordFailInvalidToken() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(400) + .setBody("mockjson/errors/error_400.json".getJson()) + ) + + setInputField(R.id.tokenEditText, "AIU8D") + setInputField(R.id.newPassEditText, "123456") + setInputField(R.id.newPassConfirmationEditText, "123456") + performClickButton() + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + private fun setInputField(resId: Int, text: String) { + onView(withId(resId) + .childAtPosition(0) + .childAtPosition(1) + ).perform( + scrollTo(), + replaceText(text) + ) + } + + private fun checkErrorById(resId: Int, func: () -> ViewAssertion) { + onView(withId(resId) + .childAtPosition(0) + .childAtPosition(2)) + .check( + func() + ) + } + + private fun performClickButton() { + onView(withId(R.id.recoveryPasswordButton)) + .perform(click()) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/forgotPassword/sendEmail/ForgotPassSendEmailTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/forgotPassword/sendEmail/ForgotPassSendEmailTest.kt new file mode 100644 index 00000000..e064d7c6 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/forgotPassword/sendEmail/ForgotPassSendEmailTest.kt @@ -0,0 +1,131 @@ +package br.com.concrete.tentacle.features.forgotPassword.sendEmail + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.rule.ActivityTestRule +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseInstrumentedTest +import br.com.concrete.tentacle.extensions.childAtPosition +import br.com.concrete.tentacle.extensions.getJson +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.Matchers +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ForgotPassSendEmailTest : BaseInstrumentedTest() { + + @get:Rule + var activityTestRule = + object : ActivityTestRule(ForgotPassSendEmailActivity::class.java) {} + + @Test + fun checkValidEmailInvalid() { + onView( + Matchers.allOf( + ViewMatchers.withId(R.id.edt), + ViewMatchers.withId(R.id.edtEmail) + .childAtPosition(0) + .childAtPosition(1) + ) + ).perform( + ViewActions.scrollTo(), + ViewActions.replaceText("teste@teste") + ) + + clickButton() + onView(withText("Digite um e-mail válido")).check(matches(isDisplayed())) + } + + @Test + fun checkValidEmailInvalidEmpty() { + onView( + Matchers.allOf( + ViewMatchers.withId(R.id.edt), + ViewMatchers.withId(R.id.edtEmail) + .childAtPosition(0) + .childAtPosition(1) + ) + ).perform( + ViewActions.scrollTo(), + ViewActions.replaceText("") + ) + + clickButton() + onView(withText("Digite um e-mail válido")).check(matches(isDisplayed())) + } + + @Test + fun sendEmailForgotPassword() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/forgotPassword/sendEmail/user.json".getJson()) + ) + + onView( + Matchers.allOf( + ViewMatchers.withId(R.id.edt), + ViewMatchers.withId(R.id.edtEmail) + .childAtPosition(0) + .childAtPosition(1) + ) + ).perform( + ViewActions.scrollTo(), + ViewActions.replaceText("teste@teste.com") + ) + + clickButton() + } + + @Test + fun sendEmailForgotPasswordError400() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(400) + .setBody("mockjson/errors/error_400.json".getJson()) + ) + checkFields() + } + + @Test + fun sendEmailForgotPasswordError404() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(404) + .setBody("mockjson/errors/error_404.json".getJson()) + ) + checkFields() + } + + private fun checkFields() { + onView( + Matchers.allOf( + ViewMatchers.withId(R.id.edt), + ViewMatchers.withId(R.id.edtEmail) + .childAtPosition(0) + .childAtPosition(1) + ) + ).perform( + ViewActions.scrollTo(), + ViewActions.replaceText("teste@teste.com") + ) + + clickButton() + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + private fun clickButton() { + onView(withId(R.id.btSend)) + .check(matches(isDisplayed())) + .perform(click()) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/gameViewComponent/GameViewTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/gameViewComponent/GameViewTest.kt new file mode 100644 index 00000000..d1ef311a --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/gameViewComponent/GameViewTest.kt @@ -0,0 +1,117 @@ +package br.com.concrete.tentacle.features.gameViewComponent + +import androidx.test.InstrumentationRegistry +import androidx.test.espresso.Espresso +import androidx.test.espresso.ViewAssertion +import androidx.test.espresso.action.ViewActions.scrollTo +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.internal.runner.junit4.statement.UiThreadStatement +import androidx.test.rule.ActivityTestRule +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.actions.SetTextInTextView +import br.com.concrete.tentacle.base.BaseInstrumentedTest +import br.com.concrete.tentacle.data.models.Game +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.testing.GameViewTestActivity +import com.google.gson.GsonBuilder +import kotlinx.android.synthetic.debug.activity_game_view_test.gameView +import org.hamcrest.CoreMatchers.not +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class GameViewTest : BaseInstrumentedTest() { + + @get:Rule + var activityTestRule = object : ActivityTestRule(GameViewTestActivity::class.java) {} + + @Before + fun setupGame() { + val json = "mockjson/game/load_game_success.json".getJson() + val gson = GsonBuilder().create() + + val game = gson.fromJson(json, Game::class.java) + + UiThreadStatement.runOnUiThread { + activityTestRule.activity.gameView.setGame(game) + } + } + + @Test + fun loadGameWithoutStatus() { + loadGames(false) + } + + @Test + fun loadGameWithStatus() { + loadGames(true) + } + + private fun loadGames(showStatus: Boolean) { + UiThreadStatement.runOnUiThread { + activityTestRule.activity.gameView.showStatusView(showStatus) + } + + Espresso.onView(withId(R.id.tvGameName)) + .perform(scrollTo()) + .check(ViewAssertions.matches(withText("The Last of Us Remastered"))) + + Espresso.onView(withId(R.id.rbGame)) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + Espresso.onView(withId(R.id.tvGameReleaseYear)) + .perform(scrollTo()) + .check(matches(withText("2014"))) + + Espresso.onView(withText("Single player")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + Espresso.onView(withText("Multiplayer")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + Espresso.onView(withText("Shooter")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + Espresso.onView(withText("Adventure")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + Espresso.onView(withText("Multiplayer")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + val assertion: ViewAssertion? + if (showStatus) { + assertion = matches(isDisplayed()) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + Espresso.onView(withId(R.id.tvGameStatus)) + .perform(SetTextInTextView("Pendente")) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + } else { + assertion = matches(not(isDisplayed())) + } + + val tvGameStatus = Espresso.onView(ViewMatchers.withId(R.id.tvGameStatus)) + val ivGameStatus = Espresso.onView(ViewMatchers.withId(R.id.ivGameStatus)) + + if (showStatus) { + tvGameStatus.perform(scrollTo()) + ivGameStatus.perform(scrollTo()) + } + + tvGameStatus.check(assertion) + ivGameStatus.check(assertion) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/home/HomeFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/home/HomeFragmentTest.kt new file mode 100644 index 00000000..b5a3202c --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/home/HomeFragmentTest.kt @@ -0,0 +1,188 @@ +package br.com.concrete.tentacle.features.home + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.matchers.RecyclerViewMatcher +import br.com.concrete.tentacle.matchers.RecyclerViewMatcher.Companion.withRecyclerView +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.CoreMatchers.not +import org.junit.Test + +class HomeFragmentTest : BaseFragmentTest() { + + override fun setupFragment() { + testFragment = HomeFragment() + } + + @Test + fun showErrorMessageAndButtonAgainOnClickReturnSuccess() { + mockWebServer.enqueue(MockResponse() + .setBody("mockjson/errors/error_400.json".getJson()) + .setResponseCode(400)) + + onView(withId(R.id.recyclerListError)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(matches(not(isDisplayed()))) + onView(withText(R.string.load_again)) + .check(matches(isDisplayed())) + onView(withId(R.id.errorDescription)) + .check(matches(withText(R.string.load_games_error_not_know))) + onView(withId(R.id.progressBarList)) + .check(matches(not(isDisplayed()))) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/home/new_home_games_success.json".getJson()) + ) + + onView(withId(R.id.buttonNameError)) + .perform(click()) + onView(withId(R.id.progressBarList)) + .check(matches(not(isDisplayed()))) + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(not(isDisplayed()))) + } + + @Test + fun showEmptyCustomLayout() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/home/load_home_games_success_empty.json".getJson()) + ) + + onView(withId(R.id.recyclerListError)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(matches(not(isDisplayed()))) + onView(withId(R.id.errorDescription)) + .check(matches(withText("A Home ainda não possui jogos novos cadastrados. Comece a cadastrar para eles aparecerem aqui!"))) + onView(withId(R.id.progressBarList)) + } + + @Test + fun showRecyclerViewWithItems() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/home/new_home_games_success.json".getJson()) + ) + + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(not(isDisplayed()))) + + onView(RecyclerViewMatcher.withRecyclerView(R.id.recyclerListView).atPosition(0)) + .check(matches(hasDescendant(withText("The Last of Us Remastered")))) + .check(matches(hasDescendant(allOf(withText("PS4"), isDisplayed())))) + .check(matches(hasDescendant(allOf(withText("PS3"), not(isDisplayed()))))) + .check(matches(hasDescendant(allOf(withText("360"), not(isDisplayed()))))) + .check(matches(hasDescendant(allOf(withText("ONE"), not(isDisplayed()))))) + .check(matches(hasDescendant(allOf(withText("3DS"), not(isDisplayed()))))) + .check(matches(hasDescendant(allOf(withText("NS"), not(isDisplayed()))))) + + onView(RecyclerViewMatcher.withRecyclerView(R.id.recyclerListView).atPosition(1)) + .check(matches(hasDescendant(withText("God of War III")))) + .check(matches(hasDescendant(allOf(withText("PS4"), not(isDisplayed()))))) + .check(matches(hasDescendant(allOf(withText("PS3"), not(isDisplayed()))))) + .check(matches(hasDescendant(allOf(withText("360"), isDisplayed())))) + .check(matches(hasDescendant(allOf(withText("ONE"), isDisplayed())))) + .check(matches(hasDescendant(allOf(withText("3DS"), not(isDisplayed()))))) + .check(matches(hasDescendant(allOf(withText("NS"), not(isDisplayed()))))) + } + + @Test + fun showErrorMessageAndButtonAgain() { + mockWebServer.enqueue(MockResponse() + .setBody("mockjson/errors/error_400.json".getJson()) + .setResponseCode(400)) + + onView(withId(R.id.recyclerListError)) + onView(withId(R.id.recyclerListView)) + .check(matches(not(isDisplayed()))) + onView(withText(R.string.load_again)) + .check(matches(isDisplayed())) + onView(withId(R.id.errorDescription)) + .check(matches(withText(R.string.load_games_error_not_know))) + onView(withId(R.id.progressBarList)) + .check(matches(not(isDisplayed()))) + } + + @Test + fun showErrorMessageAndButtonAgainOnClickReturnError() { + mockWebServer.enqueue(MockResponse() + .setBody("mockjson/errors/error_400.json".getJson()) + .setResponseCode(400)) + + onView(withId(R.id.recyclerListError)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(matches(not(isDisplayed()))) + onView(withText(R.string.load_again)) + .check(matches(isDisplayed())) + onView(withId(R.id.errorDescription)) + .check(matches(withText(R.string.load_games_error_not_know))) + onView(withId(R.id.progressBarList)) + .check(matches(not(isDisplayed()))) + + mockWebServer.enqueue(MockResponse() + .setBody("mockjson/errors/error_400.json".getJson()) + .setResponseCode(400)) + + onView(withId(R.id.buttonNameError)) + .perform(click()) + + onView(withId(R.id.recyclerListError)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(matches(not(isDisplayed()))) + onView(withText(R.string.load_again)) + .check(matches(isDisplayed())) + onView(withId(R.id.errorDescription)) + .check(matches(withText(R.string.load_games_error_not_know))) + onView(withId(R.id.progressBarList)) + .check(matches(not(isDisplayed()))) + } + + /** + * For more usages of RecyclerViewMatcher check the link below: + * https://spin.atomicobject.com/2016/04/15/espresso-testing-recyclerviews/ + */ + @Test + fun shouldShowItemsContentOnRequestSuccess() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/home/new_home_games_success.json".getJson()) + ) + + onView(withRecyclerView(R.id.recyclerListView).atPosition(1)) + .check(matches(hasDescendant(withText("God of War III")))) + .check(matches(hasDescendant(withText("Winner of over 200 game of the year awards")))) + } + + @Test + fun showRecycleViewWithItemsError426() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(426) + .setBody("mockjson/errors/error_400.json".getJson()) + ) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/lendgame/LendGameActivityTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/lendgame/LendGameActivityTest.kt new file mode 100644 index 00000000..a315fb9f --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/lendgame/LendGameActivityTest.kt @@ -0,0 +1,238 @@ +package br.com.concrete.tentacle.features.lendgame + +import android.content.Intent +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.scrollTo +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.RootMatchers +import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.rule.ActivityTestRule +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseInstrumentedTest +import br.com.concrete.tentacle.extensions.format +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.matchers.RecyclerViewMatcher +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers +import org.hamcrest.Matchers.not +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import java.util.Calendar + +@RunWith(AndroidJUnit4::class) +class LendGameActivityTest : BaseInstrumentedTest() { + + @get:Rule + var activityRule = object : ActivityTestRule(LendGameActivity::class.java) {} + + lateinit var date: String + + @Before + fun setUpDate() { + val currentDate = Calendar.getInstance() + currentDate.add(Calendar.WEEK_OF_MONTH, 2) + date = "até ${currentDate.format("dd/MM/yy")}" + } + + @Before + fun setupExtras() { + val intent = Intent() + intent.putExtra(LendGameActivity.MEDIA_ID_EXTRA, "someId") + activityRule.launchActivity(intent) + } + + @Test + fun testLoadLendSuccessWithoutReservation() { + setResponse("mockjson/library/loan/lend_response_success.json".getJson(), 200) + + onView(withId(R.id.ivGameCover)).check(matches(isDisplayed())) + onView(withId(R.id.tvGameName)).check(matches(withText("Super Meat Boy"))) + onView(withId(R.id.tvReservado)).check(matches(withText("Solicitado por"))) + onView(withId(R.id.tvRequestedBy)).check(matches(withText("Daivid Vasconcelos Leal"))) + onView(withId(R.id.tvTempoReservaLabel)).check(matches(withText("Tempo de reserva"))) + onView(withId(R.id.tvTempoReserva)).check(matches(withText("2 Semanas"))) + onView(withId(R.id.tvDate)).check(matches(withText(date))) + onView(withId(R.id.btLendGame)).perform(scrollTo()) + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())) + onView(withId(R.id.tvDateRequested)).check(matches(withText("em 14/03/19"))) + onView(withId(R.id.btRequestReturn)).check(matches(not(isDisplayed()))) + onView(withId(R.id.btLendGame)).check(matches(hasDescendant(withText("Jogo entregue")))) + } + + @Test + fun testLoadLendSuccessWithReservation() { + setResponse("mockjson/library/loan/lend_response_success_with_reservation.json".getJson(), 200) + + onView(withId(R.id.ivGameCover)).check(matches(isDisplayed())) + onView(withId(R.id.tvGameName)).check(matches(withText("Super Beat Sports"))) + onView(withId(R.id.tvReservado)).check(matches(withText("Reservado por"))) + onView(withId(R.id.tvRequestedBy)).check(matches(withText("Daivid Vasconcelos Leal"))) + onView(withId(R.id.tvTempoReservaLabel)).check(matches(withText("Tempo de reserva"))) + onView(withId(R.id.tvTempoReserva)).check(matches(withText("2 Semanas"))) + onView(withId(R.id.tvDate)).check(matches(withText("até 22/03/19"))) + onView(withId(R.id.btLendGame)).perform(scrollTo()) + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())) + onView(withId(R.id.tvDateRequested)).check(matches(withText("em 08/03/19"))) + onView(withId(R.id.btRequestReturn)).check(matches(isDisplayed())) + onView(withId(R.id.btLendGame)).check(matches(hasDescendant(withText("Jogo devolvido")))) + } + + @Test + fun testLoadLendSuccessWithoutReservationClickButton() { + setResponse("mockjson/library/loan/lend_response_success.json".getJson(), 200) + + onView(withId(R.id.ivGameCover)).check(matches(isDisplayed())) + onView(withId(R.id.tvGameName)).check(matches(withText("Super Meat Boy"))) + onView(withId(R.id.tvReservado)).check(matches(withText("Solicitado por"))) + onView(withId(R.id.tvRequestedBy)).check(matches(withText("Daivid Vasconcelos Leal"))) + onView(withId(R.id.tvTempoReservaLabel)).check(matches(withText("Tempo de reserva"))) + onView(withId(R.id.tvTempoReserva)).check(matches(withText("2 Semanas"))) + onView(withId(R.id.tvDate)).check(matches(withText(date))) + onView(withId(R.id.btLendGame)).perform(scrollTo()) + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())) + + setResponse("mockjson/library/loan/lend_response_success_updated.json".getJson(), 200) + + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())).perform(click()) + + assertTrue(activityRule.activity.isFinishing) + } + + @Test + fun testLoadLendSuccessWithoutReservationClickButtonWithoutConnection() { + setResponse("mockjson/library/loan/lend_response_success.json".getJson(), 200) + + onView(withId(R.id.ivGameCover)).check(matches(isDisplayed())) + onView(withId(R.id.tvGameName)).check(matches(withText("Super Meat Boy"))) + onView(withId(R.id.tvReservado)).check(matches(withText("Solicitado por"))) + onView(withId(R.id.tvRequestedBy)).check(matches(withText("Daivid Vasconcelos Leal"))) + onView(withId(R.id.tvTempoReservaLabel)).check(matches(withText("Tempo de reserva"))) + onView(withId(R.id.tvTempoReserva)).check(matches(withText("2 Semanas"))) + onView(withId(R.id.tvDate)).check(matches(withText(date))) + onView(withId(R.id.btLendGame)).perform(scrollTo()) + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())) + + setResponse("mockjson/errors/error_400.json".getJson(), 400) + + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())).perform(click()) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + @Test + fun testDeleteGameError() { + setResponse("mockjson/library/loan/lend_response_success.json".getJson(), 200) + setResponse("mockjson/errors/error_400.json".getJson(), 400) + + onView(withId(R.id.delete)).perform(click()) + + onView(withId(android.R.id.button1)) + .inRoot(isDialog()) + .check(matches(isDisplayed())) + .perform(click()) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + @Test + fun testLoadLendSuccessWithoutReservationClickButtonError426() { + setResponse("mockjson/library/loan/lend_response_success.json".getJson(), 200) + + onView(withId(R.id.ivGameCover)).check(matches(isDisplayed())) + onView(withId(R.id.tvGameName)).check(matches(withText("Super Meat Boy"))) + onView(withId(R.id.tvReservado)).check(matches(withText("Solicitado por"))) + onView(withId(R.id.tvRequestedBy)).check(matches(withText("Daivid Vasconcelos Leal"))) + onView(withId(R.id.tvTempoReservaLabel)).check(matches(withText("Tempo de reserva"))) + onView(withId(R.id.tvTempoReserva)).check(matches(withText("2 Semanas"))) + onView(withId(R.id.tvDate)).check(matches(withText(date))) + onView(withId(R.id.btLendGame)).perform(scrollTo()) + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())) + + setResponse("mockjson/errors/error_400.json".getJson(), 426) + + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())).perform(click()) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + @Test + fun testLoadLendError426() { + setResponse("mockjson/errors/error_400.json".getJson(), 426) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + @Test + fun testEnableMedia() { + setResponse("mockjson/library/loan/lend_response_success_disabled.json".getJson(), 200) + setResponse("mockjson/library/loan/lend_response_success_enabled.json".getJson(), 200) + + onView(withId(R.id.ivGameCover)).check(matches(isDisplayed())) + onView(withId(R.id.tvGameName)).check(matches(withText("Super Meat Boy"))) + onView(withId(R.id.tvReservado)).check(matches(withText("Solicitado por"))) + onView(withId(R.id.tvRequestedBy)).check(matches(withText("Daivid Vasconcelos Leal"))) + onView(withId(R.id.tvTempoReservaLabel)).check(matches(withText("Tempo de reserva"))) + onView(withId(R.id.tvTempoReserva)).check(matches(withText("2 Semanas"))) + onView(withId(R.id.tvDate)).check(matches(withText(date))) + onView(withId(R.id.btLendGame)).perform(scrollTo()) + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())) + + onView(withId(R.id.delete)) + .check(matches(withText("Reativar"))) + .perform(click()) + + onView(withText("O jogo Super Meat Boy será reativado e será exibido novamente na lista de \"Meus jogos\"")) + + onView(withId(android.R.id.button1)) + .inRoot(isDialog()) + .check(matches(isDisplayed())) + .perform(click()) + } + + @Test + fun testEnableMediaError400() { + setResponse("mockjson/library/loan/lend_response_success_disabled.json".getJson(), 200) + setResponse("mockjson/errors/error_400.json".getJson(), 400) + + onView(withId(R.id.ivGameCover)).check(matches(isDisplayed())) + onView(withId(R.id.tvGameName)).check(matches(withText("Super Meat Boy"))) + onView(withId(R.id.tvReservado)).check(matches(withText("Solicitado por"))) + onView(withId(R.id.tvRequestedBy)).check(matches(withText("Daivid Vasconcelos Leal"))) + onView(withId(R.id.tvTempoReservaLabel)).check(matches(withText("Tempo de reserva"))) + onView(withId(R.id.tvTempoReserva)).check(matches(withText("2 Semanas"))) + onView(withId(R.id.tvDate)).check(matches(withText(date))) + onView(withId(R.id.btLendGame)).perform(scrollTo()) + onView(withId(R.id.btLendGame)).check(matches(isDisplayed())) + + onView(withId(R.id.delete)) + .check(matches(withText("Reativar"))) + .perform(click()) + + onView(withText("O jogo Super Meat Boy será reativado e será exibido novamente na lista de \"Meus jogos\"")) + + onView(withId(android.R.id.button1)) + .inRoot(isDialog()) + .check(matches(isDisplayed())) + .perform(click()) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + private fun setResponse(json: String, code: Int) { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(code) + .setBody(json) + ) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/library/LibraryFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/library/LibraryFragmentTest.kt new file mode 100644 index 00000000..8673b41f --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/library/LibraryFragmentTest.kt @@ -0,0 +1,282 @@ +package br.com.concrete.tentacle.features.library + +import android.widget.EditText +import androidx.test.espresso.Espresso +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.Espresso.pressBack +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.extensions.waitUntil +import br.com.concrete.tentacle.features.registerGame.searchGame.SearchGameViewHolder +import br.com.concrete.tentacle.matchers.RecyclerViewMatcher.Companion.withRecyclerView +import kotlinx.android.synthetic.main.list_custom.recyclerListView +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers +import org.junit.Test + +class LibraryFragmentTest : BaseFragmentTest() { + + override fun setupFragment() { + testFragment = LibraryFragment() + } + + @Test + fun showEmptyErrorCustomLayout() { + val response = "mockjson/common/common_empty_list_success.json".getJson() + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.recyclerListError)) + .check(ViewAssertions.matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.errorDescription)) + .check(ViewAssertions.matches(withText("Nossa biblioteca ainda não tem\nnenhum jogo cadastrado. Seja o\nprimeiro a cadastrar."))) + onView(withId(R.id.progressBarList)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + } + + @Test + fun showRecycleViewWithItems() { + val response = "mockjson/library/get_library_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.progressBarList)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.recyclerListView)) + .check(ViewAssertions.matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + } + + @Test + fun showErrorMessageAndButtonLoadAgain() { + mockWebServer.enqueue(MockResponse() + .setBody("mockjson/errors/error_400.json".getJson()) + .setResponseCode(400)) + + onView(withId(R.id.recyclerListView)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.progressBarList)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.recyclerListError)) + .check(ViewAssertions.matches(isDisplayed())) + onView(withId(R.id.errorDescription)) + .check(ViewAssertions.matches(withText("Ocorreu um erro ao carregar a bilioteca de jogos.\nPor favor, tente novamente."))) + } + + @Test + fun showListWhenTypeFourLetters() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/get_library_success.json".getJson())) + + onView(withId(R.id.action_search)).perform(click()) + + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/get_library_filtered_success.json".getJson())) + + onView(ViewMatchers.isAssignableFrom(EditText::class.java)) + .perform(ViewActions.typeText("FIFA")) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListError)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + } + + @Test + fun showEmptyStateAfterSearch() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/get_library_success.json".getJson())) + + onView(withId(R.id.action_search)).perform(click()) + + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/common/common_empty_list_success.json".getJson())) + + onView(ViewMatchers.isAssignableFrom(EditText::class.java)) + .perform(ViewActions.typeText("FIFA")) + + onView(withId(R.id.recyclerListError)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.errorDescription)) + .check(ViewAssertions.matches(withText("Ops! A sua busca não retornou nenhum resultado"))) + } + + @Test + fun showProblemWithConnection() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/get_library_success.json".getJson())) + + onView(withId(R.id.action_search)).perform(click()) + + mockWebServer.enqueue(MockResponse() + .setResponseCode(400) + .setBody("mockjson/errors/error_400.json".getJson())) + + onView(ViewMatchers.isAssignableFrom(EditText::class.java)) + .perform(ViewActions.typeText("FIFA")) + + onView(withId(R.id.recyclerListError)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.errorDescription)) + .check(ViewAssertions.matches(withText("Ocorreu um erro ao carregar a bilioteca de jogos.\nPor favor, tente novamente."))) + } + + @Test + fun afterClickLoadAgainShouldMakeAnotherRequestAndShowList() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/get_library_success.json".getJson())) + + onView(withId(R.id.action_search)).perform(click()) + + mockWebServer.enqueue(MockResponse() + .setResponseCode(400) + .setBody("mockjson/errors/error_400.json".getJson())) + + onView(ViewMatchers.isAssignableFrom(EditText::class.java)) + .perform(ViewActions.typeText("FIFA")) + + onView(withId(R.id.buttonNameError)) + .perform(isDisplayed().waitUntil()) + + Espresso.pressBack() + + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/searchgame/list_game_success.json".getJson())) + + onView(withId(R.id.buttonNameError)) + .perform(click()) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListError)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + } + + @Test + fun showRecyclerViewWithItemsEndLessSuccess() { + val response = "mockjson/library/get_library_success.json".getJson() + val responseSecond = "mockjson/library/get_library_success_second.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(responseSecond) + ) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(ViewAssertions.matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + + val oldCount: Int = testFragment.recyclerListView.adapter?.itemCount!! + onView(withId(R.id.recyclerListView)).perform(scrollToPosition(testFragment.recyclerListView.adapter?.itemCount!! - 1)) + onView(withId(R.id.recyclerListView)).perform(scrollToPosition(testFragment.recyclerListView.adapter?.itemCount!! - 1)) + + Thread.sleep(2500) + + onView(withId(R.id.recyclerListView)).perform(scrollToPosition(oldCount)) + + onView(withRecyclerView(R.id.recyclerListView).atPosition(oldCount)) + .check(matches(hasDescendant(withText("JOGO FIRST")))) + } + + @Test + fun showListStateAfterSearchAndScrollingToEndSuccess() { + val response = "mockjson/library/get_library_success.json".getJson() + val responseSecond = "mockjson/library/get_library_success_second.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(responseSecond) + ) + + onView(withId(R.id.action_search)).perform(click()) + + onView(ViewMatchers.isAssignableFrom(EditText::class.java)) + .perform(ViewActions.typeText("jo")) + + pressBack() + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(ViewAssertions.matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + + val oldCount: Int = testFragment.recyclerListView.adapter?.itemCount!! + onView(withId(R.id.recyclerListView)).perform( + RecyclerViewActions.scrollToPosition( + testFragment.recyclerListView.adapter?.itemCount!! - 1 + ) + ) + + onView(withId(R.id.recyclerListView)).perform(RecyclerViewActions.scrollToPosition(oldCount)) + + Thread.sleep(2600) + + onView(withRecyclerView(R.id.recyclerListView).atPosition(0)) + .check(matches(ViewMatchers.hasDescendant(withText("JOGO FIRST")))) + } + + @Test + fun showEmptyErrorError426() { + val response = "mockjson/errors/error_400.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(426) + .setBody(response) + ) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/library/loan/LoanActivityTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/library/loan/LoanActivityTest.kt new file mode 100644 index 00000000..b9428775 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/library/loan/LoanActivityTest.kt @@ -0,0 +1,192 @@ +package br.com.concrete.tentacle.features.library.loan + +import android.content.Intent +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.scrollTo +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.Intents.intended +import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.isEnabled +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.rule.ActivityTestRule +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.matchers.RecyclerViewMatcher.Companion.withRecyclerView +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import org.hamcrest.Matchers.not +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class LoanActivityTest { + + @get:Rule + var activityRule = object : ActivityTestRule(LoanActivity::class.java) {} + + lateinit var mockWebServer: MockWebServer + + @Before + fun setUp() { + mockWebServer = MockWebServer() + mockWebServer.start(8080) + } + + @After + fun after() { + mockWebServer.shutdown() + } + + @Before + fun setupExtras() { + val intent = Intent() + intent.putExtra(LoanActivity.ID_LIBRARY_EXTRA, "someId") + activityRule.launchActivity(intent) + } + + @Test + fun testLoadLibraryWithOnePlatformAndOneOwner() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/detail_game_success.json".getJson())) + + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/get_one_owner_library.json".getJson())) + onView(withId(R.id.tvGameName)).check(matches(isDisplayed())) + onView(withId(R.id.tvGameName)).check(matches(withText("Jogo XPTO"))) + onView(withId(R.id.btPerformLoan)).check(matches(isEnabled())) + } + + @Test + fun testLoadLibraryWithPlatforms() { + setResponse() + onView(withId(R.id.tvGameName)).check(matches(isDisplayed())) + onView(withId(R.id.tvGameName)).check(matches(withText("Jogo XPTO"))) + onView(withId(R.id.btPerformLoan)).perform(scrollTo()).check(matches(not(isEnabled()))) + } + + @Test + fun checkVisibleChips() { + setResponse() + + onView(withId(R.id.chipPs4)).check(matches(isDisplayed())) + onView(withId(R.id.chipPs3)).check(matches(not(isDisplayed()))) + onView(withId(R.id.chip360)).check(matches(not(isDisplayed()))) + onView(withId(R.id.chip3ds)).check(matches(isDisplayed())) + onView(withId(R.id.chipOne)).check(matches(not(isDisplayed()))) + onView(withId(R.id.chipSwitch)).check(matches(not(isDisplayed()))) + } + + @Test + fun checkButtonState() { + setResponse() + onView(withId(R.id.chipPs4)).perform(scrollTo()).perform(click()) + onView(withId(R.id.spOwners)).perform(scrollTo()) + onView(withId(R.id.spOwners)).check(matches(withText("John Doe"))) + onView(withId(R.id.btPerformLoan)).check(matches(isEnabled())) + } + + @Test + fun showDetailGame() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/detail_game_success.json".getJson())) + + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/get_one_owner_library.json".getJson())) + + checkDetails() + + onView(withId(R.id.btPerformLoan)) + .perform(ViewActions.scrollTo()) + onView(withId(R.id.btPerformLoan)) + .check(matches(isDisplayed())) + onView(withId(R.id.btPerformLoan)) + .perform(click()) + + Assert.assertTrue(activityRule.activity.isFinishing) + } + + @Test + fun showDetailAndClickImage() { + Intents.init() + checkDetails() + + onView(withRecyclerView(R.id.recyclerView).atPosition(1)) + .perform(click()) + + intended(hasComponent(PinchToZoomActivity::class.java.name)) + Intents.release() + } + + private fun checkDetails() { + setResponse() + + val responseJson = + "mockjson/library/detail_game_success.json".getJson() + + val mediaReservationSuccess = + "mockjson/registerMedia/register_media_success.json".getJson() + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(responseJson) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(mediaReservationSuccess) + ) + + onView(withId(R.id.tvGameName)) + .check(matches(withText("Jogo XPTO"))) + onView(withId(R.id.tvGameSummary)) + .check(matches(withText("Lead your country to World Cup glory while experiencing all the fun, excitement, and drama of Football's greatest event."))) + onView(withId(R.id.tvGameReleaseYear)) + onView(withText("Sport")).check(matches(ViewMatchers.isDisplayed())) + onView(withText("Single player")).check(matches(ViewMatchers.isDisplayed())) + onView(withText("Multiplayer")).check(matches(ViewMatchers.isDisplayed())) + } + + @Test + fun checkButtonStateError426() { + setResponse() + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(426) + .setBody("mockjson/errors/error_400.json".getJson()) + ) + onView(withId(R.id.chipPs4)).perform(scrollTo()).perform(click()) + onView(withId(R.id.spOwners)).perform(scrollTo()) + onView(withId(R.id.spOwners)).check(matches(withText("John Doe"))) + onView(withId(R.id.btPerformLoan)).check(matches(isEnabled())).perform(scrollTo()).perform(click()) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + private fun setResponse() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/detail_game_success.json".getJson())) + + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/library/get_one_id_library.json".getJson())) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/loadmygames/LoadMyGamesFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/loadmygames/LoadMyGamesFragmentTest.kt new file mode 100644 index 00000000..6487e2f2 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/loadmygames/LoadMyGamesFragmentTest.kt @@ -0,0 +1,270 @@ +package br.com.concrete.tentacle.features.loadmygames + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.longClick +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition +import androidx.test.espresso.matcher.RootMatchers +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.extensions.waitUntil +import br.com.concrete.tentacle.matchers.RecyclerViewMatcher.Companion.withRecyclerView +import kotlinx.android.synthetic.main.list_custom.recyclerListView +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers.not +import org.junit.Test + +class LoadMyGamesFragmentTest : BaseFragmentTest() { + override fun setupFragment() { + testFragment = LoadMyGamesFragment() + } + + @Test + fun showEmptyErrorCustomLayout() { + val response = "mockjson/common/common_empty_list_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.recyclerListError)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(matches(not(isDisplayed()))) + onView(withId(R.id.errorDescription)) + .check(matches(withText(R.string.no_game_registered))) + onView(withId(R.id.progressBarList)) + .check(matches(not(isDisplayed()))) + } + + @Test + fun showRecycleViewWithItems() { + val response = "mockjson/loadmygames/load_my_games_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(not(isDisplayed()))) + } + + @Test + fun showErrorMessageAndButtonLoadAgain() { + mockWebServer.enqueue( + MockResponse() + .setBody("mockjson/errors/error_400.json".getJson()) + .setResponseCode(400) + ) + + onView(withId(R.id.recyclerListView)) + .check(matches(not(isDisplayed()))) + onView(withId(R.id.progressBarList)) + .check(matches(not(isDisplayed()))) + onView(withId(R.id.recyclerListError)) + .check(matches(isDisplayed())) + onView(withId(R.id.errorDescription)) + .check(matches(withText(R.string.load_games_error_not_know))) + } + + @Test + fun showRecycleViewWithItemsEndLessSuccess() { + val response = "mockjson/loadmygames/load_my_games_success.json".getJson() + val responseSecond = "mockjson/loadmygames/load_my_games_success_second.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(responseSecond) + ) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(not(isDisplayed()))) + + val oldCount: Int = testFragment.recyclerListView.adapter?.itemCount!! - 1 + onView(withId(R.id.recyclerListView)).perform(scrollToPosition(testFragment.recyclerListView.adapter?.itemCount!! - 1)) + + onView(withId(R.id.recyclerListView)).perform(scrollToPosition(testFragment.recyclerListView.adapter?.itemCount!! - 1)) + + Thread.sleep(4000) + + onView(withRecyclerView(R.id.recyclerListView).atPosition(oldCount)) + .check(matches(hasDescendant(withText("SECOND")))) + } + + @Test + fun showRecycleViewWithItemsAndLongClick() { + val response = "mockjson/loadmygames/load_my_games_success.json".getJson() + val removeGame = "mockjson/loadmygames/load_my_games_remove_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(removeGame) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + ) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + + onView( + withText("TEST")) + .perform(isDisplayed().waitUntil()) + .check(matches(isDisplayed())) + .perform(longClick()) + + onView(withText("O jogo TEST sairá da lista de \"Meus Jogos\", mas você poderá adicioná-lo novamente no futuro.")) + + onView(withText("EXCLUIR")) + .check(matches(isDisplayed())) + .inRoot(RootMatchers.isDialog()) + .check(matches(isDisplayed())) + .perform(ViewActions.click()) + + onView(withRecyclerView(R.id.recyclerListView) + .atPosition(0)) + .check(matches(isDisplayed())) + .check(matches(hasDescendant(not(withText("TEST"))))) + .check(matches(hasDescendant(not(withText("PS4"))))) + } + + @Test + fun showEmptyErrorError426() { + val response = "mockjson/errors/error_400.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(426) + .setBody(response) + ) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + @Test + fun showRecycleViewWithItemsDisabledAndEnablingMedia() { + val response = "mockjson/loadmygames/load_my_games_success_disabled.json".getJson() + val removeGame = "mockjson/loadmygames/load_my_games_enable_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(removeGame) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + ) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + + onView( + withText("TEST")) + .perform(isDisplayed().waitUntil()) + .check(matches(isDisplayed())) + .perform(longClick()) + + onView(withText("O jogo TEST será reativado e será exibido novamente na lista de \"Meus jogos\"")) + + onView(withText("Reativar")) + .check(matches(isDisplayed())) + .inRoot(RootMatchers.isDialog()) + .check(matches(isDisplayed())) + .perform(ViewActions.click()) + + onView(withRecyclerView(R.id.recyclerListView) + .atPosition(0)) + .check(matches(isDisplayed())) + .check(matches(hasDescendant(not(withText("TEST"))))) + .check(matches(hasDescendant(not(withText("PS4"))))) + + } + + @Test + fun showRecycleViewWithItemsDisabledClickEnableError404() { + val response = "mockjson/loadmygames/load_my_games_success_disabled.json".getJson() + val removeGame = "mockjson/errors/error_400.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(404) + .setBody(removeGame) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + ) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + + onView( + withText("TEST")) + .perform(isDisplayed().waitUntil()) + .check(matches(isDisplayed())) + .perform(longClick()) + + onView(withText("O jogo TEST será reativado e será exibido novamente na lista de \"Meus jogos\"")) + + onView(withText("Reativar")) + .check(matches(isDisplayed())) + .inRoot(RootMatchers.isDialog()) + .check(matches(isDisplayed())) + .perform(ViewActions.click()) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + + } +} diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/login/LoginFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/login/LoginFragmentTest.kt new file mode 100644 index 00000000..513dd7ec --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/login/LoginFragmentTest.kt @@ -0,0 +1,171 @@ +package br.com.concrete.tentacle.features.login + +import androidx.test.espresso.Espresso +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentNoActionBarNoBottomBarTest +import br.com.concrete.tentacle.extensions.getJson +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers +import org.junit.Test +import okhttp3.mockwebserver.RecordedRequest +import okhttp3.mockwebserver.Dispatcher + +class LoginFragmentTest : BaseFragmentNoActionBarNoBottomBarTest() { + + override fun setupFragment() { + testFragment = LoginFragment() + } + + @Test + fun checkInvalidEmail() { + setField("teste@teste", R.id.edtEmail) + callButtonClick() + matchesIsDisplayed(R.string.email_error) + } + + @Test + fun checkValidEmail() { + setField("teste@teste.com", R.id.edtEmail) + callButtonClick() + matchesNotIsDisplayed(R.string.email_error) + } + + @Test + fun checkPasswordEmpty() { + setField("teste@test.com", R.id.edtEmail) + setField("", R.id.edtPassword) + callButtonClick() + Espresso.onView(ViewMatchers.withId(com.google.android.material.R.id.snackbar_text)) + .check(ViewAssertions.matches(ViewMatchers.withText(R.string.verificar_campos_login))) + } + + @Test + fun checkEmailEmpty() { + setField("", R.id.edtEmail) + setField("123456", R.id.edtPassword) + callButtonClick() + Espresso.onView(ViewMatchers.withId(com.google.android.material.R.id.snackbar_text)) + .check(ViewAssertions.matches(ViewMatchers.withText(R.string.verificar_campos_login))) + } + + @Test + fun loginSuccess() { + mockWebServer.setDispatcher(getDispatcher()) + setField("teste@test.com", R.id.edtEmail) + setField("123456", R.id.edtPassword) + callButtonClick() + checkIfGoesToHome() + } + + @Test + fun loginError400() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(400) + .setBody("mockjson/errors/error_400.json".getJson()) + ) + + setField("teste@test.com", R.id.edtEmail) + setField("123456", R.id.edtPassword) + callButtonClick() + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + @Test + fun loginError401() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(401) + ) + + setField("teste@test.com", R.id.edtEmail) + setField("123456", R.id.edtPassword) + callButtonClick() + onView(withText("Usuário ou senha inválidos!")).check(matches(isDisplayed())) + } + + @Test + fun checkInvalidPassword() { + setField("123", R.id.edtPassword) + callButtonClick() + matchesIsDisplayed(R.string.password_error) + } + + @Test + fun checkValidPassword() { + setField("123456", R.id.edtPassword) + callButtonClick() + matchesNotIsDisplayed(R.string.password_error) + } + + @Test + fun loginError426() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(426) + .setBody("mockjson/errors/error_400.json".getJson()) + ) + + setField("teste@test.com", R.id.edtEmail) + setField("123456", R.id.edtPassword) + callButtonClick() + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + private fun callButtonClick() { + Espresso.onView(ViewMatchers.withId(R.id.btLogin)).perform(ViewActions.click()) + } + + private fun matchesNotIsDisplayed(idMessageError: Int) { + Espresso.onView(ViewMatchers.withText(idMessageError)).check( + ViewAssertions.matches(CoreMatchers.not(ViewMatchers.isDisplayed())) + ) + } + + private fun matchesIsDisplayed(idMessageError: Int) { + Espresso.onView(ViewMatchers.withText(idMessageError)).check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + } + + private fun getDispatcher(): Dispatcher { + return object : Dispatcher() { + override fun dispatch(request: RecordedRequest?): MockResponse { + var mockResponse: MockResponse = MockResponse().setResponseCode(404) + request?.let { + when { + request.path == "/login" -> { + mockResponse = MockResponse() + .setResponseCode(200) + .setBody("mockjson/login/login_success.json".getJson()) + } + request.path == "/refresh-token" -> { + mockResponse = + MockResponse() + .setResponseCode(200) + .setBody("mockjson/token/token_update_success.json".getJson()) + } + request.path == "/users/profile" -> { + mockResponse = + MockResponse() + .setResponseCode(200) + .setBody("mockjson/profile/get_profile_success.json".getJson()) + } + request.path == "/library/home" -> { + mockResponse = + MockResponse() + .setResponseCode(200) + .setBody("mockjson/home/load_home_games_success.json".getJson()) + } + } + } + return mockResponse + } + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/menu/MenuFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/menu/MenuFragmentTest.kt new file mode 100644 index 00000000..9c306d61 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/menu/MenuFragmentTest.kt @@ -0,0 +1,50 @@ +package br.com.concrete.tentacle.features.menu + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.extensions.getJson +import okhttp3.mockwebserver.MockResponse +import org.junit.Before +import org.junit.Test + +class MenuFragmentTest : BaseFragmentTest() { + + override fun setupFragment() { + testFragment = MenuFragment() + } + + @Before + fun setUpMenu() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/profile/get_profile_success.json".getJson()) + ) + } + + @Test + fun checkFields() { + onView(withId(R.id.name)).check(matches(withText("Damiana dos toró"))) + onView(withId(R.id.state)).check(matches(withText("Pernambuco"))) + } + + @Test + fun checkLogout() { + onView(withId(R.id.logout)).perform(click()) + onView(withText("OK")).perform(click()) + assert(activityRule.activity.isFinishing) + } + + @Test + fun checkCancelLogout() { + onView(withId(R.id.logout)).perform(click()) + onView(withText("CANCELAR")).perform(click()) + onView(withId(R.id.name)).check(matches(withText("Damiana dos toró"))) + onView(withId(R.id.state)).check(matches(withText("Pernambuco"))) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/myreservations/MyReservationFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/myreservations/MyReservationFragmentTest.kt new file mode 100644 index 00000000..7ed56ee6 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/myreservations/MyReservationFragmentTest.kt @@ -0,0 +1,239 @@ +package br.com.concrete.tentacle.features.myreservations + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.RootMatchers +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.extensions.waitUntil +import br.com.concrete.tentacle.matchers.RecyclerViewMatcher.Companion.withRecyclerView +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers.not +import org.junit.Test + +class MyReservationFragmentTest : BaseFragmentTest() { + override fun setupFragment() { + testFragment = MyReservationFragment() + } + + @Test + fun showEmptyErrorCustomLayout() { + val response = "mockjson/common/common_empty_list_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.recyclerListError)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(matches(not(isDisplayed()))) + onView(withId(R.id.errorDescription)) + .check(matches(withText("Você ainda não possui nenhum pedido de reserva."))) + onView(withId(R.id.progressBarList)) + .check(matches(not(isDisplayed()))) + } + + @Test + fun showRecycleViewWithItems() { + val response = "mockjson/myreservations/load_my_reservations_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(not(isDisplayed()))) + } + + @Test + fun showRecycleViewWithItemsExpired() { + val response = "mockjson/myreservations/load_my_reservations_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(not(isDisplayed()))) + onView(withRecyclerView(R.id.recyclerListView) + .atPosition(1)) + .check(matches(isDisplayed())) + .check(matches(hasDescendant(withText("culpa de yara")))) + .check(matches(hasDescendant(withText("06/03/19")))) + .check(matches(hasDescendant(withText("Dono: DAIVID V. LEAL")))) + } + + @Test + fun showRecycleViewWithItemsPendente() { + val response = "mockjson/myreservations/load_my_reservations_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(not(isDisplayed()))) + onView(withRecyclerView(R.id.recyclerListView) + .atPosition(2)) + .check(matches(isDisplayed())) + .check(matches(hasDescendant(withText("o jogo da vida")))) + .check(matches(hasDescendant(withText("Pendente")))) + .check(matches(hasDescendant(withText("Dono: DAIVID V. LEAL")))) + } + + @Test + fun showErrorMessageAndButtonLoadAgain() { + mockWebServer.enqueue( + MockResponse() + .setBody("mockjson/errors/error_400.json".getJson()) + .setResponseCode(400) + ) + + onView(withId(R.id.recyclerListView)) + .check(matches(not(isDisplayed()))) + onView(withId(R.id.progressBarList)) + .check(matches(not(isDisplayed()))) + onView(withId(R.id.recyclerListError)) + .check(matches(isDisplayed())) + onView(withId(R.id.errorDescription)) + .check(matches(withText("Ocorreu um erro ao carregas as reservas. Por favor, tente novamente."))) + } + + @Test + fun showErrorMessageAndClickButtonLoadAgain() { + mockWebServer.enqueue( + MockResponse() + .setBody("mockjson/errors/error_400.json".getJson()) + .setResponseCode(400) + ) + + val response = "mockjson/myreservations/load_my_reservations_success.json".getJson() + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.recyclerListError)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.errorDescription)) + .check(matches(withText("Ocorreu um erro ao carregas as reservas. Por favor, tente novamente."))) + + onView(withText(R.string.load_again)) + .perform(click()) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + } + + @Test + fun longClickDeleteExcluir() { + val response = "mockjson/myreservations/load_my_reservations_success.json".getJson() + val removeGame = "mockjson/myreservations/load_my_reservations_success_after_remove.json".getJson() + setResponse(response, 200) + setResponse(removeGame, 200) + + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(not(isDisplayed()))) + onView(withRecyclerView(R.id.recyclerListView) + .atPosition(0)) + .check(matches(isDisplayed())) + .check(matches(hasDescendant(withText("Eeee")))) + onView( + withRecyclerView(R.id.recyclerListView) + .atPosition(0)) + .check(matches(isDisplayed())) + .perform(ViewActions.longClick()) + + onView(withText("A reserva do jogo Eeee sairá da lista de \"Minhas Reservas\", mas você poderá adicioná-lo novamente no futuro.")) + + onView(withText("REMOVER")) + .check(matches(isDisplayed())) + .inRoot(RootMatchers.isDialog()) + .check(matches(isDisplayed())) + .perform(ViewActions.click()) + + onView(withRecyclerView(R.id.recyclerListView) + .atPosition(0)) + .check(matches(isDisplayed())) + .check(matches(hasDescendant(not(withText("Eeee"))))) + } + + @Test + fun longClickDeleteExcluirNotNow() { + val response = "mockjson/myreservations/load_my_reservations_success.json".getJson() + setResponse(response, 200) + + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(not(isDisplayed()))) + onView(withRecyclerView(R.id.recyclerListView) + .atPosition(0)) + .check(matches(isDisplayed())) + .check(matches(hasDescendant(withText("Eeee")))) + onView( + withRecyclerView(R.id.recyclerListView) + .atPosition(0)) + .check(matches(isDisplayed())) + .perform(ViewActions.longClick()) + + onView(withText("A reserva do jogo Eeee sairá da lista de \"Minhas Reservas\", mas você poderá adicioná-lo novamente no futuro.")) + + onView(withText("AGORA NÃO")) + .check(matches(isDisplayed())) + .inRoot(RootMatchers.isDialog()) + .check(matches(isDisplayed())) + .perform(ViewActions.click()) + + onView(withRecyclerView(R.id.recyclerListView) + .atPosition(0)) + .check(matches(isDisplayed())) + .check(matches(hasDescendant((withText("Eeee"))))) + } + + @Test + fun showRecycleViewWithItemsError426() { + setResponse("mockjson/errors/error_400.json".getJson(), 426) + + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + private fun setResponse(json: String, code: Int) { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(code) + .setBody(json) + ) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/myreservations/detail/MyReservationDetaillActivityTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/myreservations/detail/MyReservationDetaillActivityTest.kt new file mode 100644 index 00000000..70ce7e92 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/myreservations/detail/MyReservationDetaillActivityTest.kt @@ -0,0 +1,123 @@ +package br.com.concrete.tentacle.features.myreservations.detail + +import android.content.Intent +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.scrollTo +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.rule.ActivityTestRule +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseInstrumentedTest +import br.com.concrete.tentacle.extensions.getJson +import okhttp3.mockwebserver.MockResponse +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date + +class MyReservationDetaillActivityTest : BaseInstrumentedTest() { + + @get:Rule + var activityTestRule = object : ActivityTestRule(MyReservationActivity::class.java) {} + + @Before + fun setupExtras() { + val intent = Intent() + intent.putExtra(MyReservationActivity.LOAN_EXTRA_ID, "someId") + activityTestRule.launchActivity(intent) + } + + fun getDaysAfter(daysAgo: Int): Date { + val calendar = Calendar.getInstance() + calendar.add(Calendar.DAY_OF_YEAR, daysAgo) + return calendar.time + } + + @Test + fun showActiveLoan() { + val date = getDaysAfter(5) + var json = "mockjson/myreservations/detail/load_active_reservation.json" + .getJson() + .replace( + "2019-03-06T18:44:58.540Z", + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + .format(date) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(json) + ) + + onView(withId(R.id.tvGameStatus)) + .check(matches(withText("Faltam 4 dias"))) + verifyFilds() + } + + @Test + fun showPendingLoan() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/myreservations/detail/load_pending_reservation.json".getJson()) + ) + + onView(withId(R.id.tvGameStatus)) + .check(matches(withText("Pendente"))) + verifyFilds() + } + + @Test + fun showExpiredLoan() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/myreservations/detail/load_expired_reservation.json".getJson()) + ) + + onView(withId(R.id.tvGameStatus)) + .check(matches(withText("Expirado"))) + verifyFilds() + } + + private fun verifyFilds() { + onView(withId(R.id.tvGameName)) + .check(matches(withText("The Last of Us Remastered"))) + + onView(withId(R.id.tvGameReleaseYear)) + .check(matches(withText("2014"))) + + onView(withText("Single player")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + onView(withText("Multiplayer")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + onView(withText("Shooter")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + onView(withText("Adventure")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + onView(withText("Multiplayer")) + .perform(scrollTo()) + .check(matches(isDisplayed())) + + onView(withId(R.id.tvGamePlatform)) + .perform(scrollTo()) + .check(matches(withText("PS4"))) + + onView(withId(R.id.tvGameOwner)) + .perform(scrollTo()) + .check(matches(withText("FELIPE TREVISAN"))) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/myreservations/detail/TestDeleteMenuButton.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/myreservations/detail/TestDeleteMenuButton.kt new file mode 100644 index 00000000..02aca0c1 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/myreservations/detail/TestDeleteMenuButton.kt @@ -0,0 +1 @@ +package br.com.concrete.tentacle.features.myreservations.detail diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/profile/ProfileFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/profile/ProfileFragmentTest.kt new file mode 100644 index 00000000..cb8f4618 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/profile/ProfileFragmentTest.kt @@ -0,0 +1,170 @@ +package br.com.concrete.tentacle.features.profile + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.scrollTo +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.extensions.getJson +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers.not +import org.junit.Test + +class ProfileFragmentTest : BaseFragmentTest() { + + override fun setupFragment() { + testFragment = ProfileFragment() + } + + @Test + fun checkAutofillFields() { + mockResult200() + checkInputField("Damiana dos toró", R.id.userNameEditText) + checkInputField("dragons@best.com", R.id.emailEditText) + checkInputField("(81) 95874-2360", R.id.phoneEditText) + checkStateSelection("PE") + checkCitySelection("Recife") + } + + @Test + fun checkLoadErrorScreen() { + mockResult400() + onView(withId(R.id.loadError)) + .check(matches(isDisplayed())) + } + + @Test + fun checkReloadContentOnErrorScreen() { + mockResult400() + mockResult200() + onView(withId(R.id.loadError)) + .check(matches(isDisplayed())) + clickButton(R.id.buttonNameError) + checkAutofillFields() + } + + @Test + fun checkEmptyName() { + mockResult200() + setField("", R.id.userNameEditText) + clickButton(R.id.saveChangesButton) + matchesIsDisplayed("O campo nome é de preenchimento obrigatório") + } + + @Test + fun checkValidName() { + mockResult200() + setField("Teste Teste", R.id.userNameEditText) + setField("", R.id.emailEditText) // force this error in order to only make validations after click + clickButton(R.id.saveChangesButton) + matchesNotIsDisplayed("O campo nome é de preenchimento obrigatório") + } + + @Test + fun checkInvalidEmail() { + mockResult200() + setField("teste@teste", R.id.emailEditText) + clickButton(R.id.saveChangesButton) + matchesIsDisplayed("Digite um e-mail válido") + } + + @Test + fun checkValidEmail() { + mockResult200() + setField("", R.id.userNameEditText) // force this error in order to only make validations after click + setField("teste@teste.com", R.id.emailEditText) + clickButton(R.id.saveChangesButton) + matchesNotIsDisplayed("Digite um e-mail válido") + } + + @Test + fun checkEmptyPhone() { + mockResult200() + setField("", R.id.phoneEditText) + clickButton(R.id.saveChangesButton) + matchesIsDisplayed("Forneça um número de telefone válido") + } + + @Test + fun checkInvalidPhone() { + mockResult200() + setField("999999999", R.id.phoneEditText) + clickButton(R.id.saveChangesButton) + matchesIsDisplayed("Forneça um número de telefone válido") + } + + @Test + fun checkValidPhone() { + mockResult200() + setField("99 999999999", R.id.phoneEditText) + setField("", R.id.emailEditText) // force this error in order to only make validations after click + clickButton(R.id.saveChangesButton) + matchesNotIsDisplayed("Forneça um número de telefone válido") + } + + private fun mockResult200() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/profile/get_profile_success.json".getJson()) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/profile/get_states_success.json".getJson()) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/profile/get_cities_success.json".getJson()) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/profile/change_profile_success.json") + ) + } + + private fun mockResult400() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(400) + .setBody("mockjson/profile/get_profile_error.json".getJson()) + ) + } + + private fun clickButton(buttonResId: Int) { + onView(withId(buttonResId)) + .perform(scrollTo(), click()) + } + + private fun matchesNotIsDisplayed(idMessageError: String) { + onView(withText(idMessageError)) + .check( + matches(not(isDisplayed())) + ) + } + + private fun matchesIsDisplayed(idMessageError: String) { + onView(withText(idMessageError)) + .check(matches(isDisplayed())) + } + + private fun checkStateSelection(state: String) { + onView(withId(R.id.stateSearchSpinner)) + .check(matches(hasDescendant(withText(state)))) + } + + private fun checkCitySelection(city: String) { + onView(withId(R.id.citySearchSpinner)) + .check(matches(hasDescendant(withText(city)))) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/register/RegisterFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/register/RegisterFragmentTest.kt new file mode 100644 index 00000000..f2a47e28 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/register/RegisterFragmentTest.kt @@ -0,0 +1,289 @@ +package br.com.concrete.tentacle.features.register + +import androidx.test.espresso.Espresso.onData +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.scrollTo +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.withClassName +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentNoActionBarNoBottomBarTest +import br.com.concrete.tentacle.extensions.childAtPosition +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.extensions.waitUntil +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.CoreMatchers.not +import org.hamcrest.Matchers +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class RegisterFragmentTest : BaseFragmentNoActionBarNoBottomBarTest() { + + override fun setupFragment() { + testFragment = RegisterFragment() + } + + @Before + fun setMock() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/register/get_states_success.json".getJson()) + ) + } + + @Test + fun checkInvalidEmail() { + presetValidForm() + setField("teste@teste", R.id.edtEmail) + callButtonClick() + matchesIsDisplayed(R.string.email_error) + } + @Test + fun checkValidEmail() { + presetValidForm() + setField("teste@teste.com", R.id.edtEmail) + callButtonClick() + matchesNotIsDisplayed(R.string.email_error) + } + + @Test + fun checkEmptyName() { + presetValidForm() + setField("", R.id.edtUserName) + callButtonClick() + matchesIsDisplayed(R.string.name_error) + } + @Test + fun checkInvalidName() { + presetValidForm() + setField("", R.id.edtUserName) + callButtonClick() + matchesIsDisplayed(R.string.name_error) + } + @Test + fun checkValidName() { + presetValidForm() + setField("Teste Teste", R.id.edtUserName) + callButtonClick() + matchesNotIsDisplayed(R.string.name_error) + } + + @Test + fun checkEmptyPassword() { + presetValidForm() + setField("", R.id.edtPassword) + callButtonClick() + matchesIsDisplayed(R.string.password_error) + } + @Test + fun checkInvalidPassword() { + presetValidForm() + setField("123", R.id.edtPassword) + callButtonClick() + matchesIsDisplayed(R.string.password_error) + } + @Test + fun checkValidPassword() { + presetValidForm() + setField("123456", R.id.edtPassword) + callButtonClick() + matchesNotIsDisplayed(R.string.password_error) + } + + @Test + fun checkEmptyPhone() { + presetValidForm() + setField("", R.id.edtPhone) + callButtonClick() + matchesIsDisplayed(R.string.phone_error) + } + @Test + fun checkInvalidPhone() { + presetValidForm() + setField("999999999", R.id.edtPhone) + callButtonClick() + matchesIsDisplayed(R.string.phone_error) + } + @Test + fun checkValidPhone() { + presetValidForm() + setField("99 999999999", R.id.edtPhone) + callButtonClick() + matchesNotIsDisplayed(R.string.phone_error) + } + + @Test + fun checkEmptyStateSelection() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/register/get_cities_success.json".getJson()) + ) + + presetValidForm() + callButtonClick() + matchesIsDisplayed(R.string.state_error) + } + + @Test + fun checkValidStateSelection() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/register/get_cities_success.json".getJson()) + ) + + presetValidForm() + selectState() + callButtonClick() + matchesNotIsDisplayed(R.string.state_error) + } + + @Test + fun checkEmptyCitySelection() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/register/get_cities_success.json".getJson()) + ) + + presetValidForm() + selectState() + callButtonClick() + matchesIsDisplayed(R.string.city_error) + } + + @Test + fun registerSuccess() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/register/get_cities_success.json".getJson()) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/login/login_success.json".getJson()) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/token/token_update_success.json".getJson()) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/home/load_home_games_success.json".getJson()) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/profile/get_profile_success.json".getJson())) + + presetValidForm() + selectState() + selectCity() + callButtonClick() + checkIfGoesToHome() + } + + @Test + fun registerError400() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/register/get_cities_success.json".getJson()) + ) + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(400) + .setBody("mockjson/errors/error_400.json".getJson()) + ) + + presetValidForm() + selectState() + selectCity() + callButtonClick() + onView(withText("ERROR MESSAGE.")).check(matches(isDisplayed())) + } + + private fun selectState() { + onView( + Matchers.allOf( + withId(R.id.button), withText("Selecione"), + withId(R.id.spState) + .childAtPosition(0) + .childAtPosition(1) + ) + ).perform(ViewActions.scrollTo(), click()) + + onData(Matchers.anything()) + .inAdapterView( + Matchers.allOf( + withId(R.id.list), + withClassName( + Matchers.`is`("android.widget.LinearLayout")) + .childAtPosition(3) + ) + ).atPosition(16).perform(click()) + } + + private fun selectCity() { + onView( + Matchers.allOf( + withId(R.id.button), withText("Selecione"), + withId(R.id.spCity) + .childAtPosition(0) + .childAtPosition(1) + ) + ).perform(ViewActions.scrollTo(), click()) + + onData(Matchers.anything()) + .inAdapterView( + Matchers.allOf( + withId(R.id.list), + withClassName( + Matchers.`is`("android.widget.LinearLayout")) + .childAtPosition(3) + ) + ) + .atPosition(0).perform(click()) + } + + private fun presetValidForm() { + setField("teste@teste.com", R.id.edtEmail) + setField("Teste Teste", R.id.edtUserName) + setField("123456", R.id.edtPassword) + setField("99 999999999", R.id.edtPhone) + } + + private fun callButtonClick() { + onView(withId(R.id.btnCreateAccount)) + .perform(isDisplayed().waitUntil()) + .perform(scrollTo()) + .perform(click()) + } + + private fun matchesNotIsDisplayed(idMessageError: Int) { + onView(withText(idMessageError)).check( + matches(not(isDisplayed()))) + } + + private fun matchesIsDisplayed(idMessageError: Int) { + onView(withText(idMessageError)).check(matches(isDisplayed())) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/registerGame/registerMedia/RegisterMediaFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/registerGame/registerMedia/RegisterMediaFragmentTest.kt new file mode 100644 index 00000000..24004ac0 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/registerGame/registerMedia/RegisterMediaFragmentTest.kt @@ -0,0 +1,174 @@ +package br.com.concrete.tentacle.features.registerGame.registerMedia + +import android.os.Bundle +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.scrollTo +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.isEnabled +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.data.models.BaseModel +import br.com.concrete.tentacle.data.models.Game +import br.com.concrete.tentacle.extensions.fromJson +import br.com.concrete.tentacle.extensions.getJson +import com.google.gson.Gson +import okhttp3.mockwebserver.MockResponse +import org.junit.Assert +import org.junit.Test + +class RegisterMediaFragmentTest : BaseFragmentTest() { + + private val responseJson = + "mockjson/registerMedia/detail_game_success.json".getJson() + + private val mediaSaveSuccess = + "mockjson/registerMedia/register_media_success.json".getJson() + + private val mediaAlreadyRegistered = + "mockjson/errors/error_400.json".getJson() + + private val expectedGame = Gson().fromJson>(responseJson) + + override fun setupFragment() { + testFragment = RegisterMediaFragment().apply { + val args = Bundle() + args.putSerializable("game_argument", expectedGame.data._id) + arguments = args + } + } + + @Test + fun showDetailGame() { + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(responseJson) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(mediaSaveSuccess) + ) + + checkDetails() + + onView(withId(R.id.mediaRegisterButton)) + .perform(scrollTo()) + onView(withId(R.id.mediaRegisterButton)) + .check(matches(isDisplayed())) + onView(withId(R.id.mediaRegisterButton)) + .check(matches(isEnabled())) + } + + @Test + fun registerMedia() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(responseJson) + ) + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(mediaSaveSuccess) + ) + + checkDetails() + + onView(withId(R.id.mediaRegisterButton)) + .perform(scrollTo()) + onView(withId(R.id.mediaRegisterButton)) + .check(matches(isDisplayed())) + onView(withId(R.id.mediaRegisterButton)) + .check(matches(isEnabled())) + onView(withId(R.id.mediaRegisterButton)) + .perform(click()) + onView(withText("Você confirma que FIFA 06: Road to FIFA World Cup existe para a plataforma PS3?")) + .check(matches(isDisplayed())) + onView(withText("Confirmar")) + .check(matches(isDisplayed())) + .inRoot(isDialog()) + .check(matches(isDisplayed())) + .perform(click()) + + Assert.assertTrue(activityRule.activity.isFinishing) + } + + @Test + fun registerMediaErroMediaAlreadyRegistered() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(responseJson) + ) + mockWebServer.enqueue(MockResponse() + .setResponseCode(400) + .setBody(mediaAlreadyRegistered)) + + checkDetails() + + onView(withId(R.id.mediaRegisterButton)) + .perform(scrollTo()) + + onView(withId(R.id.mediaRegisterButton)) + .check(matches(isDisplayed())) + + onView(withId(R.id.mediaRegisterButton)) + .check(matches(isEnabled())) + + onView(withId(R.id.mediaRegisterButton)) + .perform(click()) + onView(withText("Você confirma que FIFA 06: Road to FIFA World Cup existe para a plataforma PS3?")) + .check(matches(isDisplayed())) + onView(withText("Confirmar")) + .check(matches(isDisplayed())) + .inRoot(isDialog()) + .check(matches(isDisplayed())) + .perform(click()) + + onView(withText("Ops! Parece que já cadastrou esse jogo.")) + .check(matches(isDisplayed())) + onView(withText("ERROR MESSAGE.")) + .check(matches(isDisplayed())) + onView(withText("Ok")) + .check(matches(isDisplayed())) + .inRoot(isDialog()) + .check(matches(isDisplayed())) + .perform(click()) + } + + private fun checkDetails() { + onView(withId(R.id.tvGameName)) + .check(matches(withText("FIFA 06: Road to FIFA World Cup"))) + onView(withId(R.id.tvGameSummary)) + .check(matches(withText("You can experience the excitement of international soccer competition in FIFA 06. Extensive coaching options give you the opportunity to take control of all of your players on the pitch and determine their formation and strategy. FIFA 06 offers game modes ranging from a tournament to individual skill games. You can also play with real players from famous international teams from around the world. Multiplayer modes let you challenge other gamers."))) + onView(withId(R.id.tvGameName)) + .check(matches(withText("FIFA 06: Road to FIFA World Cup"))) + onView(withId(R.id.tvGameReleaseYear)) + .check(matches(withText("2005"))) + onView(withText("Sport")).check(matches(isDisplayed())) + onView(withText("Single player")).check(matches(isDisplayed())) + onView(withText("Multiplayer")).check(matches(isDisplayed())) + onView(withText("Co-operative")).check(matches(isDisplayed())) + + onView(withId(R.id.chipPs3)) + .check(matches(isDisplayed())) + .perform(click()) + onView(withId(R.id.chipPs4)) + .check(matches(isDisplayed())) + onView(withId(R.id.chip360)) + .check(matches(isDisplayed())) + onView(withId(R.id.chipOne)) + .check(matches(isDisplayed())) + onView(withId(R.id.chipOne)) + .check(matches(isDisplayed())) + onView(withId(R.id.chip3ds)) + .check(matches(isDisplayed())) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/registerGame/remoteGame/RemoteGameFragmentTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/registerGame/remoteGame/RemoteGameFragmentTest.kt new file mode 100644 index 00000000..d6cb07c1 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/registerGame/remoteGame/RemoteGameFragmentTest.kt @@ -0,0 +1,99 @@ +package br.com.concrete.tentacle.features.registerGame.remoteGame + +import android.os.Bundle +import android.widget.TextView +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withParent +import androidx.test.espresso.matcher.ViewMatchers.withResourceName +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.extensions.getPartOfDate +import br.com.concrete.tentacle.extensions.toDate +import br.com.concrete.tentacle.matchers.RecyclerViewMatcher.Companion.withRecyclerView +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers +import org.hamcrest.core.AllOf.allOf +import org.hamcrest.core.IsInstanceOf.instanceOf +import org.junit.Test +import java.util.Calendar + +class RemoteGameFragmentTest : BaseFragmentTest() { + + override fun setupFragment() { + testFragment = RemoteGameFragment().apply { + val args = Bundle() + args.putSerializable("game_name", "Nome do jogo") + arguments = args + } + } + + @Test + fun shouldShowProperTitleToobar() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/registerMedia/game.json".getJson()) + ) + onView(allOf( + instanceOf(TextView::class.java), + withParent(withResourceName("action_bar")))) + .check(matches(withText("Nome do jogo"))) + } + + @Test + fun showEmptyErrorCustomLayout() { + val response = "mockjson/common/common_empty_list_success.json".getJson() + + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody(response) + ) + + onView(withId(R.id.recyclerListError)) + .check(ViewAssertions.matches(isDisplayed())) + onView(withId(R.id.recyclerListView)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.errorDescription)) + .check(ViewAssertions.matches(withText("Jogo não encontrado"))) + onView(withId(R.id.progressBarList)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + } + + @Test + fun showRecyclerViewWithItems() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/registerMedia/remote_games_success.json".getJson()) + ) + + onView(withId(R.id.recyclerListView)) + .check(matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(matches(CoreMatchers.not(isDisplayed()))) + } + + @Test + fun shouldShowItemsContentProperly() { + mockWebServer.enqueue( + MockResponse() + .setResponseCode(200) + .setBody("mockjson/registerMedia/remote_games_success.json".getJson()) + ) + + val gameName = "Super Mario 3D Land" + val releaseDate = "2011-11-03T00:00:00.000Z".toDate().getPartOfDate(Calendar.YEAR) + + onView(withRecyclerView(R.id.recyclerListView).atPosition(2)) + .check(matches(hasDescendant(withText(gameName)))) + .check(matches(hasDescendant(withText(releaseDate)))) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/features/registerGame/searchGame/SearchGameViewModelTest.kt b/app/src/androidTest/java/br/com/concrete/tentacle/features/registerGame/searchGame/SearchGameViewModelTest.kt new file mode 100644 index 00000000..46517664 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/features/registerGame/searchGame/SearchGameViewModelTest.kt @@ -0,0 +1,174 @@ +package br.com.concrete.tentacle.features.registerGame.searchGame + +import android.widget.EditText +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.Espresso.pressBack +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.typeText +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseFragmentTest +import br.com.concrete.tentacle.base.BaseSearchFragment +import br.com.concrete.tentacle.extensions.getJson +import br.com.concrete.tentacle.extensions.waitUntil +import br.com.concrete.tentacle.matchers.RecyclerViewMatcher.Companion.withRecyclerView +import kotlinx.android.synthetic.main.list_custom.* +import okhttp3.mockwebserver.MockResponse +import org.hamcrest.CoreMatchers +import org.junit.Test + +class SearchGameViewModelTest : BaseFragmentTest() { + + override fun setupFragment() { + testFragment = SearchGameFragment() + (testFragment as BaseSearchFragment) + } + + @Test + fun showListWhenTypeFourLetters() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/searchgame/list_game_success.json".getJson())) + + onView(isAssignableFrom(EditText::class.java)) + .perform(typeText("FIFA")) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListError)) + .check(matches(CoreMatchers.not(isDisplayed()))) + } + + @Test + fun showProgressBar() { + onView(isAssignableFrom(EditText::class.java)) + .perform(typeText("FIFA")) + + onView(withId(R.id.recyclerListError)) + .check(matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.recyclerListView)) + .check(matches(CoreMatchers.not(isDisplayed()))) + } + + @Test + fun showButtonWhenListIsEmpty() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/searchgame/list_game_empty_success.json".getJson())) + + onView(isAssignableFrom(EditText::class.java)) + .perform(typeText("FIFA")) + + onView(withId(R.id.recyclerListError)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.errorDescription)) + .check(matches(withText(R.string.first_game_register))) + } + + @Test + fun showProblemWithConnection() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(400) + .setBody("mockjson/errors/error_400.json".getJson())) + + onView(isAssignableFrom(EditText::class.java)) + .perform(typeText("FIFA")) + + onView(withId(R.id.recyclerListError)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(matches(CoreMatchers.not(isDisplayed()))) + onView(withId(R.id.errorDescription)) + .check(matches(withText(R.string.load_games_error_not_know))) + } + + @Test + fun afterClickLoadAgainShouldMakeAnotherRequestAndShowList() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(400) + .setBody("mockjson/errors/error_400.json".getJson())) + + onView(isAssignableFrom(EditText::class.java)) + .perform(typeText("FIFA")) + + onView(withId(R.id.buttonNameError)) + .perform(isDisplayed().waitUntil()) + + pressBack() + + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/searchgame/list_game_success.json".getJson())) + + onView(withId(R.id.buttonNameError)) + .perform(click()) + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListError)) + .check(matches(CoreMatchers.not(isDisplayed()))) + } + + @Test + fun afterSearchAndVerifyItemIsOk() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/searchgame/list_game_success.json".getJson())) + + onView(isAssignableFrom(EditText::class.java)) + .perform(typeText("FIFA")) + + pressBack() + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + + onView(withRecyclerView(R.id.recyclerListView).atPosition(0)) + .check(matches(ViewMatchers.hasDescendant(withText("Jogo 01")))) + } + + @Test + fun afterSearchAndScrollingToEndSuccess() { + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/searchgame/list_game_success.json".getJson())) + mockWebServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody("mockjson/searchgame/list_game_success_second.json".getJson())) + + onView(isAssignableFrom(EditText::class.java)) + .perform(typeText("jo")) + + pressBack() + + onView(withId(R.id.recyclerListView)) + .perform(isDisplayed().waitUntil()) + onView(withId(R.id.recyclerListView)) + .check(ViewAssertions.matches(isDisplayed())) + onView(withId(R.id.recyclerListError)) + .check(ViewAssertions.matches(CoreMatchers.not(isDisplayed()))) + + val oldCount: Int = testFragment.recyclerListView.adapter?.itemCount!! + onView(withId(R.id.recyclerListView)).perform( + RecyclerViewActions.scrollToPosition( + testFragment.recyclerListView.adapter?.itemCount!! - 1 + ) + ) + + onView(withId(R.id.recyclerListView)).perform(RecyclerViewActions.scrollToPosition(oldCount)) + + Thread.sleep(2600) + + onView(withRecyclerView(R.id.recyclerListView).atPosition(oldCount)) + .check(matches(ViewMatchers.hasDescendant(withText("JOGO FIRST")))) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/matchers/RecyclerViewMatcher.kt b/app/src/androidTest/java/br/com/concrete/tentacle/matchers/RecyclerViewMatcher.kt new file mode 100644 index 00000000..b0bebcac --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/matchers/RecyclerViewMatcher.kt @@ -0,0 +1,63 @@ +package br.com.concrete.tentacle.matchers + +import android.content.res.Resources +import android.view.View +import org.hamcrest.Matcher +import org.hamcrest.TypeSafeMatcher +import androidx.recyclerview.widget.RecyclerView +import org.hamcrest.Description + +class RecyclerViewMatcher(private val recyclerViewId: Int) { + + companion object { + fun withRecyclerView(recyclerViewId: Int): RecyclerViewMatcher = + RecyclerViewMatcher(recyclerViewId) + } + + fun atPosition(position: Int): Matcher = atPositionOnView(position, -1) + + private fun atPositionOnView(position: Int, targetViewId: Int): Matcher { + + return object : TypeSafeMatcher() { + var resources: Resources? = null + var childView: View? = null + + override fun describeTo(description: Description) { + var idDescription = Integer.toString(recyclerViewId) + if (this.resources != null) { + try { + idDescription = this.resources!!.getResourceName(recyclerViewId) + } catch (var4: Resources.NotFoundException) { + idDescription = String.format( + "%s (resource name not found)", + *arrayOf(Integer.valueOf(recyclerViewId)) + ) + } + } + + description.appendText("with id: $idDescription") + } + + public override fun matchesSafely(view: View): Boolean { + + this.resources = view.resources + + if (childView == null) { + val recyclerView = view.rootView.findViewById(recyclerViewId) as RecyclerView? + if (recyclerView != null && recyclerView.id == recyclerViewId) { + childView = recyclerView.findViewHolderForAdapterPosition(position)!!.itemView + } else { + return false + } + } + + return if (targetViewId == -1) { + view === childView + } else { + val targetView = childView!!.findViewById(targetViewId) + view === targetView + } + } + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/util/LayoutChangeCallback.kt b/app/src/androidTest/java/br/com/concrete/tentacle/util/LayoutChangeCallback.kt new file mode 100644 index 00000000..527d5fa5 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/util/LayoutChangeCallback.kt @@ -0,0 +1,40 @@ +package br.com.concrete.tentacle.util + +import android.view.View +import androidx.test.espresso.IdlingResource +import org.hamcrest.Matcher + +class LayoutChangeCallback + internal constructor( + private val matcher: Matcher + ) : IdlingResource, View.OnLayoutChangeListener { + private var callback: IdlingResource.ResourceCallback? = null + private var matched = false + + override fun getName(): String { + return "Layout change callback" + } + + override fun isIdleNow(): Boolean { + return matched + } + + override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback) { + this.callback = callback + } + + override fun onLayoutChange( + v: View, + left: Int, + top: Int, + right: Int, + bottom: Int, + oldLeft: Int, + oldTop: Int, + oldRight: Int, + oldBottom: Int + ) { + matched = matcher.matches(v) + callback!!.onTransitionToIdle() + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/util/RecyclerPositionViewMatcher.kt b/app/src/androidTest/java/br/com/concrete/tentacle/util/RecyclerPositionViewMatcher.kt new file mode 100644 index 00000000..65570549 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/util/RecyclerPositionViewMatcher.kt @@ -0,0 +1,71 @@ +package br.com.concrete.tentacle.util + +import android.content.res.Resources +import android.view.View +import androidx.annotation.IdRes +import androidx.recyclerview.widget.RecyclerView +import org.hamcrest.Description +import org.hamcrest.Matcher +import org.hamcrest.TypeSafeMatcher + +class RecyclerPositionViewMatcher private constructor(private val recyclerViewId: Int) { + + private fun atPosition(position: Int): Matcher { + return atPositionOnView(position, -1) + } + + private fun atPositionOnView(position: Int, targetViewId: Int): Matcher { + + return object : TypeSafeMatcher() { + internal var resources: Resources? = null + internal var childView: View? = null + + override fun describeTo(description: Description) { + var idDescription = Integer.toString(recyclerViewId) + if (this.resources != null) { + try { + idDescription = this.resources!!.getResourceName(recyclerViewId) + } catch (var4: Resources.NotFoundException) { + idDescription = String.format("%s (resource printerName not found)", recyclerViewId) + } + } + + description.appendText("with id: $idDescription") + } + + public override fun matchesSafely(view: View): Boolean { + + this.resources = view.resources + + if (childView == null) { + val recyclerView = view.rootView.findViewById(recyclerViewId) + if (recyclerView != null && recyclerView.id == recyclerViewId) { + val childViewHolder = recyclerView.findViewHolderForAdapterPosition(position) + if (childViewHolder != null) + childView = childViewHolder.itemView + } else { + return false + } + } + + if (targetViewId == -1) { + return view === childView + } else { + val targetView = childView!!.findViewById(targetViewId) + return view === targetView + } + } + } + } + + companion object { + + fun withRecyclerView(@IdRes recyclerViewId: Int, atPosition: Int): Matcher { + return RecyclerPositionViewMatcher(recyclerViewId).atPosition(atPosition) + } + + fun withRecyclerViewAndViewId(@IdRes recyclerViewId: Int, atPosition: Int, viewId: Int): Matcher { + return RecyclerPositionViewMatcher(recyclerViewId).atPositionOnView(atPosition, viewId) + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/concrete/tentacle/util/TentacleTestRunner.kt b/app/src/androidTest/java/br/com/concrete/tentacle/util/TentacleTestRunner.kt new file mode 100644 index 00000000..c49243e6 --- /dev/null +++ b/app/src/androidTest/java/br/com/concrete/tentacle/util/TentacleTestRunner.kt @@ -0,0 +1,15 @@ +package br.com.concrete.tentacle.util + +import android.app.Application +import android.content.Context +import androidx.test.runner.AndroidJUnitRunner +import br.com.concrete.tentacle.TentacleTestApp + +/** + * Custom runner to disable dependency injection. + */ +class TentacleTestRunner : AndroidJUnitRunner() { + override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application { + return super.newApplication(cl, TentacleTestApp::class.java.name, context) + } +} \ No newline at end of file diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..598bb72d --- /dev/null +++ b/app/src/debug/AndroidManifest.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/common/common_empty_list_success.json b/app/src/debug/assets/mockjson/common/common_empty_list_success.json new file mode 100644 index 00000000..e94d6fab --- /dev/null +++ b/app/src/debug/assets/mockjson/common/common_empty_list_success.json @@ -0,0 +1,6 @@ +{ + "data": { + "list": [], + "count": 0 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/errors/error_400.json b/app/src/debug/assets/mockjson/errors/error_400.json new file mode 100644 index 00000000..1b6f56e9 --- /dev/null +++ b/app/src/debug/assets/mockjson/errors/error_400.json @@ -0,0 +1,6 @@ +{ + "message": [ + "ERROR MESSAGE." + ], + "statusCode":400 +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/errors/error_401.json b/app/src/debug/assets/mockjson/errors/error_401.json new file mode 100644 index 00000000..a883db7a --- /dev/null +++ b/app/src/debug/assets/mockjson/errors/error_401.json @@ -0,0 +1,6 @@ +{ + "message": [ + "ERROR MESSAGE." + ], + "statusCode":401 +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/errors/error_404.json b/app/src/debug/assets/mockjson/errors/error_404.json new file mode 100644 index 00000000..acef1745 --- /dev/null +++ b/app/src/debug/assets/mockjson/errors/error_404.json @@ -0,0 +1,6 @@ +{ + "message": [ + "ERROR MESSAGE." + ], + "statusCode":404 +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/forgotPassword/passwordRecovery/restore_password_success.json b/app/src/debug/assets/mockjson/forgotPassword/passwordRecovery/restore_password_success.json new file mode 100644 index 00000000..b0215270 --- /dev/null +++ b/app/src/debug/assets/mockjson/forgotPassword/passwordRecovery/restore_password_success.json @@ -0,0 +1,10 @@ +{ + "message": [ + "Login realizado" + ], + "data": { + "accessToken": "TOKEN", + "refreshToken": "REFRESH_TOKEN", + "tokenType": "JWT" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/forgotPassword/sendEmail/user.json b/app/src/debug/assets/mockjson/forgotPassword/sendEmail/user.json new file mode 100644 index 00000000..63f24fdf --- /dev/null +++ b/app/src/debug/assets/mockjson/forgotPassword/sendEmail/user.json @@ -0,0 +1,19 @@ +{ + "message": [ + "Usuário atualizado" + ], + "data": { + "_id": "5c810617647c2c0023ccdb28", + "city": "Recife", + "email": "maherbson.concrete@gmail.com", + "name": "Maherbson", + "phone": "81 983541434", + "state": { + "_id": "5a107a691592ca19f7b4a860", + "initials": "PE", + "name": "Pernambuco" + }, + "createdAt": "2019-03-07T11:52:55.957Z", + "updatedAt": "2019-03-12T19:05:24.821Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/game/load_game_success.json b/app/src/debug/assets/mockjson/game/load_game_success.json new file mode 100644 index 00000000..542f04dd --- /dev/null +++ b/app/src/debug/assets/mockjson/game/load_game_success.json @@ -0,0 +1,90 @@ +{ + "_id": "5c66feafdf4b530023a72773", + "title": "The Last of Us Remastered", + "id": 6036, + "aggregated_rating": 97.4, + "aggregated_rating_count": 11, + "cover": { + "id": 70754, + "height": 1500, + "image_id": "co1ile", + "width": 1062 + }, + "first_release_date": "2014-07-29T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + } + ], + "genres": [ + { + "id": 5, + "name": "Shooter", + "slug": "shooter" + }, + { + "id": 31, + "name": "Adventure", + "slug": "adventure" + } + ], + "name": "The Last of Us Remastered", + "screenshots": [ + { + "id": 9463, + "height": 728, + "image_id": "wdzisarwedjsqeg5iah4", + "width": 1365 + }, + { + "id": 9464, + "height": 1080, + "image_id": "oz4rxwu528bmckp1qqzt", + "width": 1920 + }, + { + "id": 9465, + "height": 1080, + "image_id": "d64boffz2tkso1cuj1lk", + "width": 1920 + }, + { + "id": 9466, + "height": 1080, + "image_id": "lqz37tmv2r4lcjaxczwx", + "width": 1920 + }, + { + "id": 9467, + "height": 720, + "image_id": "iqzfweidhwepz0bf4fhr", + "width": 1280 + } + ], + "slug": "the-last-of-us-remastered", + "summary": "Winner of over 200 game of the year awards, The Last of Us has been remastered for the PlayStation®4. Now featuring higher resolution character models, improved shadows and lighting, in addition to several other gameplay improvements. \n \nAbandoned cities reclaimed by nature. A population decimated by a modern plague. Survivors are killing each other for food, weapons whatever they can get their hands on. Joel, a brutal survivor, and Ellie, a brave young teenage girl who is wise beyond her years, must work together if they hope to survive their journey across the US. \n \nThe Last of Us: Remastered includes the Abandoned Territories Map Pack, Reclaimed Territories Map Pack, and the critically acclaimed The Last of Us: Left Behind Single Player campaign. \n \nPS4 PRO ENHANCED: \n- PS4 Pro HD \n- Dynamic 4K Gaming \n- Greater Draw Distance \n- Visual FX \n- Vivid Textures \n- Deep Shadows \n- High Fidelity Assets \n- HDR", + "url": "https://www.igdb.com/games/the-last-of-us-remastered", + "videos": [ + { + "id": 2231, + "name": "Teaser", + "video_id": "Z2RlTvdNjzQ" + }, + { + "id": 2641, + "name": "E3 Trailer", + "video_id": "6UNn6EIRsL0" + } + ], + "formattedReleaseDate": "29/07/2014", + "createdBy": "5c179fa83b6274002239a00b", + "createdAt": "2019-02-15T18:02:23.079Z", + "updatedAt": "2019-02-15T18:02:23.079Z" +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/home/load_home_games_success.json b/app/src/debug/assets/mockjson/home/load_home_games_success.json new file mode 100644 index 00000000..17c8530f --- /dev/null +++ b/app/src/debug/assets/mockjson/home/load_home_games_success.json @@ -0,0 +1,107 @@ +{ + "data": { + "list": [ + { + "_id": "1", + "title": "Jogo 1", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-14T16:27:45.355Z", + "updatedAt": "2019-01-14T16:27:45.355Z" + }, + { + "_id": "2", + "title": "Jogo 2", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-23T21:32:04.829Z", + "updatedAt": "2019-01-23T21:32:04.829Z" + }, + { + "_id": "5c49f7c86d40b70023ca6319", + "title": "Jogo 3", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-24T17:37:12.180Z", + "updatedAt": "2019-01-24T17:37:12.180Z" + }, + { + "_id": "5c49b33a0124e4002334b1bc", + "title": "Jogo 4", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-24T12:44:42.081Z", + "updatedAt": "2019-01-24T12:44:42.081Z" + }, + { + "_id": "5c460f9df2cb790023617ab6", + "title": "Jogo 5", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-21T18:29:49.058Z", + "updatedAt": "2019-01-21T18:29:49.058Z" + }, + { + "_id": "5c38c18bdd09c90023fad1a7", + "title": "Jogo 6", + "createdBy": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL" + }, + "createdAt": "2019-01-11T16:17:15.215Z", + "updatedAt": "2019-01-11T16:17:15.215Z" + }, + { + "_id": "5c48ca7ae07db9002375d5a6", + "title": "Jogo 7", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-23T20:11:38.515Z", + "updatedAt": "2019-01-23T20:11:38.515Z" + }, + { + "_id": "5c40aac1576d4d00237448f5", + "title": "Jogo 8", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-17T16:18:09.328Z", + "updatedAt": "2019-01-17T16:18:09.328Z" + }, + { + "_id": "5c38d24bef33b700234351dd", + "title": "Jogo 9", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-11T17:28:43.975Z", + "updatedAt": "2019-01-11T17:28:43.975Z" + }, + { + "_id": "5c4b67c6c0221400235b5226", + "title": "Jogo 10 ", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-25T19:47:18.810Z", + "updatedAt": "2019-01-25T19:47:18.810Z" + } + ], + "count": 45 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/home/load_home_games_success_empty.json b/app/src/debug/assets/mockjson/home/load_home_games_success_empty.json new file mode 100644 index 00000000..e94d6fab --- /dev/null +++ b/app/src/debug/assets/mockjson/home/load_home_games_success_empty.json @@ -0,0 +1,6 @@ +{ + "data": { + "list": [], + "count": 0 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/home/new_home_games_success.json b/app/src/debug/assets/mockjson/home/new_home_games_success.json new file mode 100644 index 00000000..a067d673 --- /dev/null +++ b/app/src/debug/assets/mockjson/home/new_home_games_success.json @@ -0,0 +1,267 @@ +{ + "data": { + "list": [ + { + "_id": "5c66feafdf4b530023a72773", + "id": 6036, + "aggregated_rating": 97.4, + "aggregated_rating_count": 11, + "name": "The Last of Us Remastered", + "screenshots": [ + { + "id": 9463, + "height": 728, + "image_id": "wdzisarwedjsqeg5iah4", + "width": 1365 + }, + { + "id": 9464, + "height": 1080, + "image_id": "oz4rxwu528bmckp1qqzt", + "width": 1920 + }, + { + "id": 9465, + "height": 1080, + "image_id": "d64boffz2tkso1cuj1lk", + "width": 1920 + }, + { + "id": 9466, + "height": 1080, + "image_id": "lqz37tmv2r4lcjaxczwx", + "width": 1920 + }, + { + "id": 9467, + "height": 720, + "image_id": "iqzfweidhwepz0bf4fhr", + "width": 1280 + } + ], + "summary": "Winner of over 200 game of the year awards, The Last of Us has been remastered for the PlayStation®4. Now featuring higher resolution character models, improved shadows and lighting, in addition to several other gameplay improvements. \n \nAbandoned cities reclaimed by nature. A population decimated by a modern plague. Survivors are killing each other for food, weapons whatever they can get their hands on. Joel, a brutal survivor, and Ellie, a brave young teenage girl who is wise beyond her years, must work together if they hope to survive their journey across the US. \n \nThe Last of Us: Remastered includes the Abandoned Territories Map Pack, Reclaimed Territories Map Pack, and the critically acclaimed The Last of Us: Left Behind Single Player campaign. \n \nPS4 PRO ENHANCED: \n- PS4 Pro HD \n- Dynamic 4K Gaming \n- Greater Draw Distance \n- Visual FX \n- Vivid Textures \n- Deep Shadows \n- High Fidelity Assets \n- HDR", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0, + "createdBy": { + "_id": "5c179fa83b6274002239a00b", + "name": "FELIPE TREVISAN" + }, + "createdAt": "2019-02-15T18:02:23.079Z", + "updatedAt": "2019-02-15T18:02:23.079Z" + }, + { + "_id": "5c66feafdf4b530023a72773", + "id": 6036, + "aggregated_rating": 97.4, + "aggregated_rating_count": 11, + "name": "God of War III", + "screenshots": [ + { + "id": 9463, + "height": 728, + "image_id": "wdzisarwedjsqeg5iah4", + "width": 1365 + }, + { + "id": 9464, + "height": 1080, + "image_id": "oz4rxwu528bmckp1qqzt", + "width": 1920 + }, + { + "id": 9465, + "height": 1080, + "image_id": "d64boffz2tkso1cuj1lk", + "width": 1920 + }, + { + "id": 9466, + "height": 1080, + "image_id": "lqz37tmv2r4lcjaxczwx", + "width": 1920 + }, + { + "id": 9467, + "height": 720, + "image_id": "iqzfweidhwepz0bf4fhr", + "width": 1280 + } + ], + "summary": "Winner of over 200 game of the year awards", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 2, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0, + "createdBy": { + "_id": "5c179fa83b6274002239a00b", + "name": "FELIPE TREVISAN" + }, + "createdAt": "2019-02-15T18:02:23.079Z", + "updatedAt": "2019-02-15T18:02:23.079Z" + }, + { + "_id": "5c66feafdf4b530023a72773", + "id": 6036, + "aggregated_rating": 97.4, + "aggregated_rating_count": 11, + "name": "The Last of Us Remastered", + "screenshots": [ + { + "id": 9463, + "height": 728, + "image_id": "wdzisarwedjsqeg5iah4", + "width": 1365 + }, + { + "id": 9464, + "height": 1080, + "image_id": "oz4rxwu528bmckp1qqzt", + "width": 1920 + }, + { + "id": 9465, + "height": 1080, + "image_id": "d64boffz2tkso1cuj1lk", + "width": 1920 + }, + { + "id": 9466, + "height": 1080, + "image_id": "lqz37tmv2r4lcjaxczwx", + "width": 1920 + }, + { + "id": 9467, + "height": 720, + "image_id": "iqzfweidhwepz0bf4fhr", + "width": 1280 + } + ], + "summary": "Winner of over 200 game of the year awards, The Last of Us has been remastered for the PlayStation®4. Now featuring higher resolution character models, improved shadows and lighting, in addition to several other gameplay improvements. \n \nAbandoned cities reclaimed by nature. A population decimated by a modern plague. Survivors are killing each other for food, weapons whatever they can get their hands on. Joel, a brutal survivor, and Ellie, a brave young teenage girl who is wise beyond her years, must work together if they hope to survive their journey across the US. \n \nThe Last of Us: Remastered includes the Abandoned Territories Map Pack, Reclaimed Territories Map Pack, and the critically acclaimed The Last of Us: Left Behind Single Player campaign. \n \nPS4 PRO ENHANCED: \n- PS4 Pro HD \n- Dynamic 4K Gaming \n- Greater Draw Distance \n- Visual FX \n- Vivid Textures \n- Deep Shadows \n- High Fidelity Assets \n- HDR", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0, + "createdBy": { + "_id": "5c179fa83b6274002239a00b", + "name": "FELIPE TREVISAN" + }, + "createdAt": "2019-02-15T18:02:23.079Z", + "updatedAt": "2019-02-15T18:02:23.079Z" + }, + { + "_id": "5c66feafdf4b530023a72773", + "id": 6036, + "aggregated_rating": 97.4, + "aggregated_rating_count": 11, + "name": "The Last of Us Remastered", + "screenshots": [ + { + "id": 9463, + "height": 728, + "image_id": "wdzisarwedjsqeg5iah4", + "width": 1365 + }, + { + "id": 9464, + "height": 1080, + "image_id": "oz4rxwu528bmckp1qqzt", + "width": 1920 + }, + { + "id": 9465, + "height": 1080, + "image_id": "d64boffz2tkso1cuj1lk", + "width": 1920 + }, + { + "id": 9466, + "height": 1080, + "image_id": "lqz37tmv2r4lcjaxczwx", + "width": 1920 + }, + { + "id": 9467, + "height": 720, + "image_id": "iqzfweidhwepz0bf4fhr", + "width": 1280 + } + ], + "summary": "Winner of over 200 game of the year awards, The Last of Us has been remastered for the PlayStation®4. Now featuring higher resolution character models, improved shadows and lighting, in addition to several other gameplay improvements. \n \nAbandoned cities reclaimed by nature. A population decimated by a modern plague. Survivors are killing each other for food, weapons whatever they can get their hands on. Joel, a brutal survivor, and Ellie, a brave young teenage girl who is wise beyond her years, must work together if they hope to survive their journey across the US. \n \nThe Last of Us: Remastered includes the Abandoned Territories Map Pack, Reclaimed Territories Map Pack, and the critically acclaimed The Last of Us: Left Behind Single Player campaign. \n \nPS4 PRO ENHANCED: \n- PS4 Pro HD \n- Dynamic 4K Gaming \n- Greater Draw Distance \n- Visual FX \n- Vivid Textures \n- Deep Shadows \n- High Fidelity Assets \n- HDR", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0, + "createdBy": { + "_id": "5c179fa83b6274002239a00b", + "name": "FELIPE TREVISAN" + }, + "createdAt": "2019-02-15T18:02:23.079Z", + "updatedAt": "2019-02-15T18:02:23.079Z" + }, + { + "_id": "5c66feafdf4b530023a72773", + "id": 6036, + "aggregated_rating": 97.4, + "aggregated_rating_count": 11, + "name": "The Last of Us Remastered", + "screenshots": [ + { + "id": 9463, + "height": 728, + "image_id": "wdzisarwedjsqeg5iah4", + "width": 1365 + }, + { + "id": 9464, + "height": 1080, + "image_id": "oz4rxwu528bmckp1qqzt", + "width": 1920 + }, + { + "id": 9465, + "height": 1080, + "image_id": "d64boffz2tkso1cuj1lk", + "width": 1920 + }, + { + "id": 9466, + "height": 1080, + "image_id": "lqz37tmv2r4lcjaxczwx", + "width": 1920 + }, + { + "id": 9467, + "height": 720, + "image_id": "iqzfweidhwepz0bf4fhr", + "width": 1280 + } + ], + "summary": "Winner of over 200 game of the year awards, The Last of Us has been remastered for the PlayStation®4. Now featuring higher resolution character models, improved shadows and lighting, in addition to several other gameplay improvements. \n \nAbandoned cities reclaimed by nature. A population decimated by a modern plague. Survivors are killing each other for food, weapons whatever they can get their hands on. Joel, a brutal survivor, and Ellie, a brave young teenage girl who is wise beyond her years, must work together if they hope to survive their journey across the US. \n \nThe Last of Us: Remastered includes the Abandoned Territories Map Pack, Reclaimed Territories Map Pack, and the critically acclaimed The Last of Us: Left Behind Single Player campaign. \n \nPS4 PRO ENHANCED: \n- PS4 Pro HD \n- Dynamic 4K Gaming \n- Greater Draw Distance \n- Visual FX \n- Vivid Textures \n- Deep Shadows \n- High Fidelity Assets \n- HDR", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0, + "createdBy": { + "_id": "5c179fa83b6274002239a00b", + "name": "FELIPE TREVISAN" + }, + "createdAt": "2019-02-15T18:02:23.079Z", + "updatedAt": "2019-02-15T18:02:23.079Z" + } + ], + "count": 45 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/detail_game_success.json b/app/src/debug/assets/mockjson/library/detail_game_success.json new file mode 100644 index 00000000..deb39f8d --- /dev/null +++ b/app/src/debug/assets/mockjson/library/detail_game_success.json @@ -0,0 +1,89 @@ +{ + "message": [ + "Jogo encontrado" + ], + "data": { + "_id": "5c93d5ca3e379400232111f2", + "id": 5471, + "aggregated_rating": 76.25, + "aggregated_rating_count": 8, + "cover": { + "id": 6576, + "height": 805, + "image_id": "lu8auuzna0umyezck32z", + "width": 646 + }, + "first_release_date": "2014-04-15T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + }, + { + "id": 4, + "name": "Split screen", + "slug": "split-screen" + } + ], + "genres": [ + { + "id": 14, + "name": "Sport", + "slug": "sport" + } + ], + "name": "Jogo XPTO", + "screenshots": [ + { + "id": 22467, + "height": 1079, + "image_id": "llnspsijream7wmcg169", + "width": 1920 + }, + { + "id": 22468, + "height": 1080, + "image_id": "isapun9yabn4qtrctnfm", + "width": 1920 + }, + { + "id": 22469, + "height": 1080, + "image_id": "qxkhag1idi8rhtpul3ns", + "width": 1920 + }, + { + "id": 22470, + "height": 1080, + "image_id": "hzaqviom8der9nvn2vm5", + "width": 1920 + }, + { + "id": 22471, + "height": 1080, + "image_id": "doqkft3opih5eanhv84o", + "width": 1920 + } + ], + "slug": "2014-fifa-world-cup-brazil", + "summary": "Lead your country to World Cup glory while experiencing all the fun, excitement, and drama of Football's greatest event.", + "url": "https://www.igdb.com/games/2014-fifa-world-cup-brazil", + "videos": [ + { + "id": 2310, + "name": "Trailer", + "video_id": "uO1HNUoDzxQ" + } + ], + "formattedReleaseDate": "15/04/2014", + "createdBy": "5c815f1a349f31002315fcd9", + "createdAt": "2019-03-21T18:19:54.885Z", + "updatedAt": "2019-03-21T18:19:54.885Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/filter_itens.json b/app/src/debug/assets/mockjson/library/filter_itens.json new file mode 100644 index 00000000..c9542616 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/filter_itens.json @@ -0,0 +1,21 @@ +[ + { + "title":"Plataformas", + "icon":"", + "subitems":[ + "Playstation 3", + "Playstation 4", + "XBox 360", + "XBox One", + "Nintendo 3DS", + "Nintendo Switch" + ] + }, + { + "title":"Status do jogo", + "icon":"", + "subitems":[ + "Mostrar jogos indisponíveis" + ] + } +] \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/get_library_after_filter_success.json b/app/src/debug/assets/mockjson/library/get_library_after_filter_success.json new file mode 100644 index 00000000..ef12b7c9 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/get_library_after_filter_success.json @@ -0,0 +1,311 @@ +{ + "data": { + "list": [ + { + "_id": "5c65d598860df20023ec8489", + "title": "culpa de yara", + "createdBy": "5c1ab15c7c0f4f002272357f", + "createdAt": "2019-02-14T20:54:48.896Z", + "updatedAt": "2019-02-15T03:04:59.608Z", + "name": "culpa de yara", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c65d5a8860df20023ec848a", + "owner": "5c1ab15c7c0f4f002272357f", + "ownerName": "DAIVID V. LEAL", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c65d298860df20023ec8484", + "title": "o jogo da vida", + "createdBy": "5c1ab15c7c0f4f002272357f", + "createdAt": "2019-02-14T20:42:00.187Z", + "updatedAt": "2019-02-15T03:04:59.608Z", + "name": "o jogo da vida", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c65d38c860df20023ec8486", + "owner": "5c1ab15c7c0f4f002272357f", + "ownerName": "DAIVID V. LEAL", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c64438f352d58002358f362", + "title": "Fifa 2015", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-02-13T16:19:27.658Z", + "updatedAt": "2019-02-15T03:04:59.593Z", + "name": "Fifa 2015", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c644392352d58002358f363", + "owner": "5c1ab12e7c0f4f002272357e", + "ownerName": "JOAO DAS NEVES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c64437e352d58002358f35e", + "title": "Fifa 2018", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-02-13T16:19:10.059Z", + "updatedAt": "2019-02-15T03:04:59.593Z", + "name": "Fifa 2018", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c644380352d58002358f35f", + "owner": "5c1ab12e7c0f4f002272357e", + "ownerName": "JOAO DAS NEVES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c644374352d58002358f35c", + "title": "Fifa 2017", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-02-13T16:19:00.173Z", + "updatedAt": "2019-02-15T03:04:59.593Z", + "name": "Fifa 2017", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c644376352d58002358f35d", + "owner": "5c1ab12e7c0f4f002272357e", + "ownerName": "JOAO DAS NEVES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c61733d2da00d00231f99c5", + "title": "jogo 11", + "createdBy": "5c505219aa9b7a00236f58e0", + "createdAt": "2019-02-11T13:06:05.595Z", + "updatedAt": "2019-02-15T03:04:59.592Z", + "name": "jogo 11", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c6173402da00d00231f99c6", + "owner": "5c505219aa9b7a00236f58e0", + "ownerName": "MAHERBSON DANTAS", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c6173202da00d00231f99c3", + "title": "jogo 8", + "createdBy": "5c505219aa9b7a00236f58e0", + "createdAt": "2019-02-11T13:05:36.411Z", + "updatedAt": "2019-02-15T03:04:59.592Z", + "name": "jogo 8", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c6173222da00d00231f99c4", + "owner": "5c505219aa9b7a00236f58e0", + "ownerName": "MAHERBSON DANTAS", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c5dbabbcc06180023fd7df9", + "title": "Fifa 19", + "createdBy": "5c5dba8ccc06180023fd7df7", + "createdAt": "2019-02-08T17:22:03.801Z", + "updatedAt": "2019-02-15T03:04:59.592Z", + "name": "Fifa 19", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c5dbac2cc06180023fd7dfa", + "owner": "5c5dba8ccc06180023fd7df7", + "ownerName": "FELIPE TREVISAN", + "ownerState": "5a107a691592ca19f7b4a867", + "ownerCity": "Santa Rosa" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [ + { + "_id": "5c5dbf6ecc06180023fd7e0c", + "owner": "5c5dba8ccc06180023fd7df7", + "ownerName": "FELIPE TREVISAN", + "ownerState": "5a107a691592ca19f7b4a867", + "ownerCity": "Santa Rosa" + } + ], + "mediaNintendo3ds": [ + { + "_id": "5c5dbf63cc06180023fd7e0b", + "owner": "5c5dba8ccc06180023fd7df7", + "ownerName": "FELIPE TREVISAN", + "ownerState": "5a107a691592ca19f7b4a867", + "ownerCity": "Santa Rosa" + } + ], + "mediaNintendoSwitch": [ + { + "_id": "5c5dbf59cc06180023fd7e09", + "owner": "5c5dba8ccc06180023fd7df7", + "ownerName": "FELIPE TREVISAN", + "ownerState": "5a107a691592ca19f7b4a867", + "ownerCity": "Santa Rosa" + } + ], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c5c9239838e5a0023986fc3", + "title": "Motorola", + "createdBy": "5c58603ff8e6ef002376a5d2", + "createdAt": "2019-02-07T20:16:57.109Z", + "updatedAt": "2019-02-15T03:04:59.591Z", + "name": "Motorola", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c5c923a838e5a0023986fc4", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c5c66d143371d0023bbb35a", + "title": "game 5", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-02-07T17:11:45.322Z", + "updatedAt": "2019-02-15T03:04:59.591Z", + "name": "game 5", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c5c66d343371d0023bbb35b", + "owner": "5c1ab12e7c0f4f002272357e", + "ownerName": "JOAO DAS NEVES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + } + ], + "count": 33 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/get_library_error.json b/app/src/debug/assets/mockjson/library/get_library_error.json new file mode 100644 index 00000000..a5c533c3 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/get_library_error.json @@ -0,0 +1,5 @@ +{ + "message": [ + "Dados inválidos para o campo 'Plataforma'." + ] +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/get_library_filtered_success.json b/app/src/debug/assets/mockjson/library/get_library_filtered_success.json new file mode 100644 index 00000000..21a8c7ec --- /dev/null +++ b/app/src/debug/assets/mockjson/library/get_library_filtered_success.json @@ -0,0 +1,97 @@ +{ + "data": { + "list": [ + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c644387352d58002358f360", + "name": "Fifa 2016", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c64437e352d58002358f35e", + "name": "Fifa 2018", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c644374352d58002358f35c", + "name": "Fifa 2017", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c5dbabbcc06180023fd7df9", + "name": "Fifa 19", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c49cbaf0124e4002334b1be", + "name": "fifa 12", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c460f9df2cb790023617ab6", + "name": "FIFA", + "mediaPs3Count": 2, + "mediaPs4Count": 2, + "mediaXbox360Count": 2, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c38d24bef33b700234351dd", + "name": "Fifa 18", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c38c18bdd09c90023fad1a7", + "name": "FIFA 2019", + "mediaPs3Count": 2, + "mediaPs4Count": 5, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 2 + } + ], + "count": 9 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/get_library_search_game_fifa_success.json b/app/src/debug/assets/mockjson/library/get_library_search_game_fifa_success.json new file mode 100644 index 00000000..4f44269b --- /dev/null +++ b/app/src/debug/assets/mockjson/library/get_library_search_game_fifa_success.json @@ -0,0 +1,457 @@ +{ + "data": { + "list": [ + { + "_id": "5c64438f352d58002358f362", + "title": "Fifa 2015", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-02-13T16:19:27.658Z", + "updatedAt": "2019-02-15T03:04:59.593Z", + "name": "Fifa 2015", + "mediaPs3": [ + { + "_id": "5c66fc6a9321750023d9998f", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaPs4": [ + { + "_id": "5c644392352d58002358f363", + "owner": "5c1ab12e7c0f4f002272357e", + "ownerName": "JOAO DAS NEVES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + }, + { + "_id": "5c66fc739321750023d99990", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaXbox360": [ + { + "_id": "5c66fc829321750023d99991", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaXboxOne": [ + { + "_id": "5c66fc8f9321750023d99992", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [ + { + "_id": "5c66fc989321750023d99993", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c644387352d58002358f360", + "title": "Fifa 2016", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-02-13T16:19:19.355Z", + "updatedAt": "2019-02-15T03:04:59.593Z", + "name": "Fifa 2016", + "mediaPs3": [], + "mediaPs4": [], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [ + { + "_id": "5c644389352d58002358f361", + "owner": "5c1ab12e7c0f4f002272357e", + "ownerName": "JOAO DAS NEVES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c64437e352d58002358f35e", + "title": "Fifa 2018", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-02-13T16:19:10.059Z", + "updatedAt": "2019-02-15T03:04:59.593Z", + "name": "Fifa 2018", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c644380352d58002358f35f", + "owner": "5c1ab12e7c0f4f002272357e", + "ownerName": "JOAO DAS NEVES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c644374352d58002358f35c", + "title": "Fifa 2017", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-02-13T16:19:00.173Z", + "updatedAt": "2019-02-15T03:04:59.593Z", + "name": "Fifa 2017", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c644376352d58002358f35d", + "owner": "5c1ab12e7c0f4f002272357e", + "ownerName": "JOAO DAS NEVES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c5dbabbcc06180023fd7df9", + "title": "Fifa 19", + "createdBy": "5c5dba8ccc06180023fd7df7", + "createdAt": "2019-02-08T17:22:03.801Z", + "updatedAt": "2019-02-15T03:04:59.592Z", + "name": "Fifa 19", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c5dbac2cc06180023fd7dfa", + "owner": "5c5dba8ccc06180023fd7df7", + "ownerName": "FELIPE TREVISAN", + "ownerState": "5a107a691592ca19f7b4a867", + "ownerCity": "Santa Rosa" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [ + { + "_id": "5c5dbf6ecc06180023fd7e0c", + "owner": "5c5dba8ccc06180023fd7df7", + "ownerName": "FELIPE TREVISAN", + "ownerState": "5a107a691592ca19f7b4a867", + "ownerCity": "Santa Rosa" + } + ], + "mediaNintendo3ds": [ + { + "_id": "5c5dbf63cc06180023fd7e0b", + "owner": "5c5dba8ccc06180023fd7df7", + "ownerName": "FELIPE TREVISAN", + "ownerState": "5a107a691592ca19f7b4a867", + "ownerCity": "Santa Rosa" + } + ], + "mediaNintendoSwitch": [ + { + "_id": "5c5dbf59cc06180023fd7e09", + "owner": "5c5dba8ccc06180023fd7df7", + "ownerName": "FELIPE TREVISAN", + "ownerState": "5a107a691592ca19f7b4a867", + "ownerCity": "Santa Rosa" + } + ], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c49cbaf0124e4002334b1be", + "title": "fifa 12", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-01-24T14:29:03.388Z", + "updatedAt": "2019-02-15T03:04:59.454Z", + "name": "fifa 12", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c49eb396d40b70023ca6318", + "owner": "5c49e7766d40b70023ca6316", + "ownerName": "E-MAIL 4", + "ownerState": "5a107a681592ca19f7b4a853", + "ownerCity": "Amaturá" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [ + { + "_id": "5c49fe806d40b70023ca631d", + "owner": "5c49fe556d40b70023ca631b", + "ownerName": "EMAIL 5", + "ownerState": "5a107a681592ca19f7b4a854", + "ownerCity": "Cutias" + } + ], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c460f9df2cb790023617ab6", + "title": "FIFA", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-01-21T18:29:49.058Z", + "updatedAt": "2019-02-15T03:04:59.453Z", + "name": "FIFA", + "mediaPs3": [ + { + "_id": "5c5059d5aa9b7a00236f58e4", + "owner": "5c5059a5aa9b7a00236f58e2", + "ownerName": "LEO MALKES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + }, + { + "_id": "5c66fc269321750023d9998a", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaPs4": [ + { + "_id": "5c50948329d7100023ebb769", + "owner": "5c505219aa9b7a00236f58e0", + "ownerName": "MAHERBSON DANTAS", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + }, + { + "_id": "5c66fc319321750023d9998b", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaXbox360": [ + { + "_id": "5c5352e0906fb50023e50738", + "owner": "5c1ab15c7c0f4f002272357f", + "ownerName": "DAIVID V. LEAL", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + }, + { + "_id": "5c66fc3a9321750023d9998c", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaXboxOne": [ + { + "_id": "5c66f8529321750023d99989", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaNintendo3ds": [ + { + "_id": "5c66fc489321750023d9998d", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaNintendoSwitch": [ + { + "_id": "5c66fc509321750023d9998e", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaPs3Count": 2, + "mediaPs4Count": 2, + "mediaXbox360Count": 2, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c38d24bef33b700234351dd", + "title": "Fifa 18", + "createdBy": "5c1ab12e7c0f4f002272357e", + "createdAt": "2019-01-11T17:28:43.975Z", + "updatedAt": "2019-02-15T03:04:59.605Z", + "name": "Fifa 18", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c5dbad6cc06180023fd7dfb", + "owner": "5c5dba8ccc06180023fd7df7", + "ownerName": "FELIPE TREVISAN", + "ownerState": "5a107a691592ca19f7b4a867", + "ownerCity": "Santa Rosa" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c38c18bdd09c90023fad1a7", + "title": "FIFA 2019", + "createdBy": "5c1ab15c7c0f4f002272357f", + "createdAt": "2019-01-11T16:17:15.215Z", + "updatedAt": "2019-02-15T03:04:59.605Z", + "name": "FIFA 2019", + "mediaPs3": [ + { + "_id": "5c3cb3e6098fab0023f6b0d1", + "owner": "5c1ab15c7c0f4f002272357f", + "ownerName": "DAIVID V. LEAL", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + }, + { + "_id": "5c586104f8e6ef002376a5d5", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaPs4": [ + { + "_id": "5c3cb70f098fab0023f6b0d4", + "owner": "5c1ab15c7c0f4f002272357f", + "ownerName": "DAIVID V. LEAL", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + }, + { + "_id": "5c49e53e6d40b70023ca6313", + "owner": "5c49d1220104540023701195", + "ownerName": "EMAIL EMAIL", + "ownerState": "5a107a681592ca19f7b4a853", + "ownerCity": "Anori" + }, + { + "_id": "5c51da3d5da9790023080d68", + "owner": "5c505219aa9b7a00236f58e0", + "ownerName": "MAHERBSON DANTAS", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + }, + { + "_id": "5c53274cbe36dd0023ea2c32", + "owner": "5c2d129dd957060023385a1b", + "ownerName": "RWYEG", + "ownerState": "5a107a681592ca19f7b4a854", + "ownerCity": "Cutias" + }, + { + "_id": "5c66f3d29321750023d99981", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaXbox360": [ + { + "_id": "5c5860f7f8e6ef002376a5d4", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "YARA", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [ + { + "_id": "5c4a0a556d40b70023ca6333", + "owner": "5c4a096a6d40b70023ca632f", + "ownerName": "LETICIA GUEDIX", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + }, + { + "_id": "5c5dbe60cc06180023fd7e06", + "owner": "5c1ab12e7c0f4f002272357e", + "ownerName": "JOAO DAS NEVES", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaPs3Count": 2, + "mediaPs4Count": 5, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 2 + } + ], + "count": 9 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/get_library_success.json b/app/src/debug/assets/mockjson/library/get_library_success.json new file mode 100644 index 00000000..1f35b8f3 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/get_library_success.json @@ -0,0 +1,164 @@ +{ + "data": { + "list": [ + { + "_id": "5c66feafdf4b530023a72773", + "id": 6036, + "aggregated_rating": 97.4, + "aggregated_rating_count": 11, + "cover": { + "id": 70754, + "height": 1500, + "image_id": "co1ile", + "width": 1062 + }, + "name": "JOGO 1", + "formattedReleaseDate": "29/07/2014", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c66f80a9321750023d99987", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c66f41d9321750023d99984", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c66f3fb9321750023d99982", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c65e161860df20023ec848e", + "name": "jogo test", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c65d598860df20023ec8489", + "name": "culpa de yara", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c65d298860df20023ec8484", + "name": "o jogo da vida", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c65cae5860df20023ec8475", + "name": "jhv,jhv", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64612f352d58002358f367", + "name": "😉😍🙂😎", + "mediaPs3Count": 1, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + } + ], + "count": 88 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/get_library_success_second.json b/app/src/debug/assets/mockjson/library/get_library_success_second.json new file mode 100644 index 00000000..e602e951 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/get_library_success_second.json @@ -0,0 +1,164 @@ +{ + "data": { + "list": [ + { + "_id": "5c66feafdf4b530023a72773", + "id": 6036, + "aggregated_rating": 97.4, + "aggregated_rating_count": 11, + "cover": { + "id": 70754, + "height": 1500, + "image_id": "co1ile", + "width": 1062 + }, + "name": "JOGO FIRST", + "formattedReleaseDate": "29/07/2014", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c66f80a9321750023d99987", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c66f41d9321750023d99984", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c66f3fb9321750023d99982", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c65e161860df20023ec848e", + "name": "jogo test", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c65d598860df20023ec8489", + "name": "culpa de yara", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c65d298860df20023ec8484", + "name": "o jogo da vida", + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c65cae5860df20023ec8475", + "name": "jhv,jhv", + "mediaPs3Count": 0, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64612f352d58002358f367", + "name": "😉😍🙂😎", + "mediaPs3Count": 1, + "mediaPs4Count": 0, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + }, + { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015", + "mediaPs3Count": 1, + "mediaPs4Count": 2, + "mediaXbox360Count": 1, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 1 + } + ], + "count": 88 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/get_one_id_library.json b/app/src/debug/assets/mockjson/library/get_one_id_library.json new file mode 100644 index 00000000..0e50226b --- /dev/null +++ b/app/src/debug/assets/mockjson/library/get_one_id_library.json @@ -0,0 +1,114 @@ +{ + "data": { + "_id": "5c93d5ca3e379400232111f2", + "id": 5471, + "aggregated_rating": 76.25, + "aggregated_rating_count": 8, + "cover": { + "id": 6576, + "height": 805, + "image_id": "lu8auuzna0umyezck32z", + "width": 646 + }, + "first_release_date": "2014-04-15T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + }, + { + "id": 4, + "name": "Split screen", + "slug": "split-screen" + } + ], + "genres": [ + { + "id": 14, + "name": "Sport", + "slug": "sport" + } + ], + "name": "Jogo XPTO", + "screenshots": [ + { + "id": 22467, + "height": 1079, + "image_id": "llnspsijream7wmcg169", + "width": 1920 + }, + { + "id": 22468, + "height": 1080, + "image_id": "isapun9yabn4qtrctnfm", + "width": 1920 + }, + { + "id": 22469, + "height": 1080, + "image_id": "qxkhag1idi8rhtpul3ns", + "width": 1920 + }, + { + "id": 22470, + "height": 1080, + "image_id": "hzaqviom8der9nvn2vm5", + "width": 1920 + }, + { + "id": 22471, + "height": 1080, + "image_id": "doqkft3opih5eanhv84o", + "width": 1920 + } + ], + "slug": "2014-fifa-world-cup-brazil", + "summary": "Lead your country to World Cup glory while experiencing all the fun, excitement, and drama of Football's greatest event.", + "url": "https://www.igdb.com/games/2014-fifa-world-cup-brazil", + "videos": [ + { + "id": 2310, + "name": "Trailer", + "video_id": "uO1HNUoDzxQ" + } + ], + "formattedReleaseDate": "15/04/2014", + "createdBy": "5c815f1a349f31002315fcd9", + "createdAt": "2019-03-21T18:19:54.885Z", + "updatedAt": "2019-03-21T18:19:54.885Z", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c9b9e5bb297ed0023e8ff51", + "owner": "5c8267812e75f4002361813f", + "ownerName": "John Doe", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [ + { + "_id": "5c93d60a3e379400232111f3", + "owner": "5c815f1a349f31002315fcd9", + "ownerName": "Yara Taciane", + "ownerState": "5a107a681592ca19f7b4a854", + "ownerCity": "Itaubal" + } + ], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 1, + "mediaNintendoSwitchCount": 0 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/get_one_library_success.json b/app/src/debug/assets/mockjson/library/get_one_library_success.json new file mode 100644 index 00000000..5e9bdf0f --- /dev/null +++ b/app/src/debug/assets/mockjson/library/get_one_library_success.json @@ -0,0 +1,181 @@ +{ + "data": { + "_id": "5c794f6e169826002349874b", + "id": 36950, + "aggregated_rating": 65, + "aggregated_rating_count": 9, + "cover": { + "id": 71030, + "height": 960, + "image_id": "co1it2", + "width": 677 + }, + "first_release_date": "2019-02-22T00:00:00.000Z", + "game_modes": [ + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + } + ], + "genres": [ + { + "id": 5, + "name": "Shooter", + "slug": "shooter" + }, + { + "id": 12, + "name": "Role-playing (RPG)", + "slug": "role-playing-rpg" + }, + { + "id": 31, + "name": "Adventure", + "slug": "adventure" + } + ], + "name": "Anthem", + "screenshots": [ + { + "id": 44213, + "height": 1080, + "image_id": "bwjri6c8g1n94haoztgm", + "width": 1920 + }, + { + "id": 44214, + "height": 1080, + "image_id": "nknebu6mov0enphbwxib", + "width": 1920 + }, + { + "id": 44215, + "height": 1080, + "image_id": "opsyuak5nsg11p9wvqcj", + "width": 1920 + }, + { + "id": 44216, + "height": 1080, + "image_id": "ta5m1c6vp6226kdblwge", + "width": 1920 + }, + { + "id": 44217, + "height": 1080, + "image_id": "uols5jinxtna1w9dgxdw", + "width": 1920 + }, + { + "id": 213489, + "height": 744, + "image_id": "f1pvnnlhyqvbtstk3zbj", + "width": 1324 + }, + { + "id": 213490, + "height": 716, + "image_id": "tp3tsdlzfkdp1hhofmb1", + "width": 1276 + } + ], + "slug": "anthem", + "summary": "Anthem is a shared-world action RPG, where players can delve into a vast landscape teeming with amazing technology and forgotten treasures. This is a world where Freelancers are called upon to defeat savage beasts, ruthless marauders, and forces plotting to conquer humanity.", + "url": "https://www.igdb.com/games/anthem", + "videos": [ + { + "id": 14281, + "name": "Teaser", + "video_id": "wi0Uq7QmKm4" + }, + { + "id": 14303, + "name": "Gameplay video", + "video_id": "cyJMA0-3i4U" + }, + { + "id": 20444, + "name": "Trailer", + "video_id": "ZFwylDNpgFc" + }, + { + "id": 20994, + "name": "Gameplay video", + "video_id": "p-nKttWT7JM" + }, + { + "id": 21987, + "name": "Trailer", + "video_id": "lPBUlFOhFks" + }, + { + "id": 23650, + "name": "Trailer", + "video_id": "jZizDqnz7oY" + }, + { + "id": 24034, + "name": "Trailer", + "video_id": "yJo19lIZWJY" + }, + { + "id": 24247, + "name": "Trailer", + "video_id": "lWfDwyvbkpk" + }, + { + "id": 24248, + "name": "Gameplay video", + "video_id": "2drI_iT4NUg" + }, + { + "id": 24748, + "name": "Trailer", + "video_id": "oh2RHMcfHkg" + }, + { + "id": 24796, + "name": "Trailer", + "video_id": "DPf-EATqFng" + }, + { + "id": 24953, + "name": "Trailer", + "video_id": "wka5RovFEo8" + } + ], + "formattedReleaseDate": "22/02/2019", + "createdBy": "5c5dba8ccc06180023fd7df7", + "createdAt": "2019-03-01T15:27:42.437Z", + "updatedAt": "2019-03-01T15:27:42.437Z", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c8270952e75f4002361814e", + "owner": "5c818df8349f31002315fcfc", + "ownerName": "Trevisan", + "ownerState": "5a107a681592ca19f7b4a851", + "ownerCity": "Acrelândia" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [ + { + "_id": "5c82aaee73caf20023d6803a", + "owner": "5c818df8349f31002315fcfc", + "ownerName": "Trevisan", + "ownerState": "5a107a681592ca19f7b4a851", + "ownerCity": "Acrelândia" + } + ], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 1, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/get_one_owner_library.json b/app/src/debug/assets/mockjson/library/get_one_owner_library.json new file mode 100644 index 00000000..0e56d032 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/get_one_owner_library.json @@ -0,0 +1,106 @@ +{ + "data": { + "_id": "5c93d5ca3e379400232111f2", + "id": 5471, + "aggregated_rating": 76.25, + "aggregated_rating_count": 8, + "cover": { + "id": 6576, + "height": 805, + "image_id": "lu8auuzna0umyezck32z", + "width": 646 + }, + "first_release_date": "2014-04-15T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + }, + { + "id": 4, + "name": "Split screen", + "slug": "split-screen" + } + ], + "genres": [ + { + "id": 14, + "name": "Sport", + "slug": "sport" + } + ], + "name": "Jogo XPTO", + "screenshots": [ + { + "id": 22467, + "height": 1079, + "image_id": "llnspsijream7wmcg169", + "width": 1920 + }, + { + "id": 22468, + "height": 1080, + "image_id": "isapun9yabn4qtrctnfm", + "width": 1920 + }, + { + "id": 22469, + "height": 1080, + "image_id": "qxkhag1idi8rhtpul3ns", + "width": 1920 + }, + { + "id": 22470, + "height": 1080, + "image_id": "hzaqviom8der9nvn2vm5", + "width": 1920 + }, + { + "id": 22471, + "height": 1080, + "image_id": "doqkft3opih5eanhv84o", + "width": 1920 + } + ], + "slug": "2014-fifa-world-cup-brazil", + "summary": "Lead your country to World Cup glory while experiencing all the fun, excitement, and drama of Football's greatest event.", + "url": "https://www.igdb.com/games/2014-fifa-world-cup-brazil", + "videos": [ + { + "id": 2310, + "name": "Trailer", + "video_id": "uO1HNUoDzxQ" + } + ], + "formattedReleaseDate": "15/04/2014", + "createdBy": "5c815f1a349f31002315fcd9", + "createdAt": "2019-03-21T18:19:54.885Z", + "updatedAt": "2019-03-21T18:19:54.885Z", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c9b9e5bb297ed0023e8ff51", + "owner": "5c8267812e75f4002361813f", + "ownerName": "John Doe", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Recife" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/loan/lend_response_success.json b/app/src/debug/assets/mockjson/library/loan/lend_response_success.json new file mode 100644 index 00000000..84adf597 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/loan/lend_response_success.json @@ -0,0 +1,61 @@ +{ + "message": [ + "Mídia encontrada" + ], + "data": { + "_id": "5c829d4173caf20023d68034", + "active": true, + "game": "5c8197b6349f31002315fd08", + "platform": "NINTENDO3DS", + "owner": "5c8148ef349f31002315fcca", + "createdAt": "2019-03-08T16:50:09.239Z", + "updatedAt": "2019-03-08T16:50:09.239Z", + "activeLoan": { + "_id": "5c8ae22f1994610023bf0476", + "requestedBy": "5c815595349f31002315fccf", + "requestedAt": "2019-03-14T23:22:23.193Z", + "requestedByName": "Daivid Vasconcelos Leal", + "requestedByState": "5a107a691592ca19f7b4a860", + "requestedByCity": "Paulista" + }, + "gameData": { + "_id": "5c8197b6349f31002315fd08", + "id": 885, + "aggregated_rating": 85.25, + "cover": { + "id": 65991, + "height": 600, + "image_id": "htvoqoyhppqlrjto0ixz", + "width": 479 + }, + "first_release_date": "2010-10-20T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + } + ], + "genres": [ + { + "id": 8, + "name": "Platform", + "slug": "platform" + }, + { + "id": 31, + "name": "Adventure", + "slug": "adventure" + }, + { + "id": 32, + "name": "Indie", + "slug": "indie" + } + ], + "name": "Super Meat Boy", + "summary": "Super Meat Boy is a tough as nails platformer where you play as an animated cube of meat who's trying to save his girlfriend (who happens to be made of bandages) from an evil fetus in a jar wearing a tux.", + "formattedReleaseDate": "20/10/2010" + } + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/loan/lend_response_success_disabled.json b/app/src/debug/assets/mockjson/library/loan/lend_response_success_disabled.json new file mode 100644 index 00000000..a11e848b --- /dev/null +++ b/app/src/debug/assets/mockjson/library/loan/lend_response_success_disabled.json @@ -0,0 +1,61 @@ +{ + "message": [ + "Mídia encontrada" + ], + "data": { + "_id": "5c829d4173caf20023d68034", + "active": false, + "game": "5c8197b6349f31002315fd08", + "platform": "NINTENDO3DS", + "owner": "5c8148ef349f31002315fcca", + "createdAt": "2019-03-08T16:50:09.239Z", + "updatedAt": "2019-03-08T16:50:09.239Z", + "activeLoan": { + "_id": "5c8ae22f1994610023bf0476", + "requestedBy": "5c815595349f31002315fccf", + "requestedAt": "2019-03-14T23:22:23.193Z", + "requestedByName": "Daivid Vasconcelos Leal", + "requestedByState": "5a107a691592ca19f7b4a860", + "requestedByCity": "Paulista" + }, + "gameData": { + "_id": "5c8197b6349f31002315fd08", + "id": 885, + "aggregated_rating": 85.25, + "cover": { + "id": 65991, + "height": 600, + "image_id": "htvoqoyhppqlrjto0ixz", + "width": 479 + }, + "first_release_date": "2010-10-20T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + } + ], + "genres": [ + { + "id": 8, + "name": "Platform", + "slug": "platform" + }, + { + "id": 31, + "name": "Adventure", + "slug": "adventure" + }, + { + "id": 32, + "name": "Indie", + "slug": "indie" + } + ], + "name": "Super Meat Boy", + "summary": "Super Meat Boy is a tough as nails platformer where you play as an animated cube of meat who's trying to save his girlfriend (who happens to be made of bandages) from an evil fetus in a jar wearing a tux.", + "formattedReleaseDate": "20/10/2010" + } + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/loan/lend_response_success_enabled.json b/app/src/debug/assets/mockjson/library/loan/lend_response_success_enabled.json new file mode 100644 index 00000000..84281c8a --- /dev/null +++ b/app/src/debug/assets/mockjson/library/loan/lend_response_success_enabled.json @@ -0,0 +1,20 @@ +{ + "message": [ + "Mídia removida" + ], + "data": { + "active": true, + "_id": "5c8278c72e75f40023618173", + "game": { + "_id": "5c8278c32e75f40023618172", + "name": "Asphalt 3D" + }, + "platform": "NINTENDOSWITCH", + "owner": { + "_id": "5c810617647c2c0023ccdb28", + "name": "Maherbson" + }, + "createdAt": "2019-03-08T14:14:31.453Z", + "updatedAt": "2019-03-08T14:14:31.453Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/loan/lend_response_success_updated.json b/app/src/debug/assets/mockjson/library/loan/lend_response_success_updated.json new file mode 100644 index 00000000..0a375afe --- /dev/null +++ b/app/src/debug/assets/mockjson/library/loan/lend_response_success_updated.json @@ -0,0 +1,27 @@ +{ + "message": [ + "Empréstimo atualizado" + ], + "data": { + "requestedAt": "2019-02-20T16:57:33.698Z", + "_id": "5c6da1ae70d4e60023af7fe9", + "media": { + "_id": "5c4af2a1f9d9720023542eec", + "platform": "PS4" + }, + "requestedBy": { + "_id": "5c58603ff8e6ef002376a5d2", + "name": "YARA" + }, + "mediaOwner": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "game": { + "_id": "5c4af29bf9d9720023542eeb", + "name": "Monster Hunter: World" + }, + "estimatedReturnDate": "2019-03-07T16:39:49.694Z", + "loanDate": "2019-02-21T16:39:49.694Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/loan/lend_response_success_with_reservation.json b/app/src/debug/assets/mockjson/library/loan/lend_response_success_with_reservation.json new file mode 100644 index 00000000..bad79952 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/loan/lend_response_success_with_reservation.json @@ -0,0 +1,68 @@ +{ + "message": [ + "Mídia encontrada" + ], + "data": { + "_id": "5c8199a2349f31002315fd0a", + "active": true, + "game": "5c81997d349f31002315fd09", + "platform": "PS4", + "owner": "5c8148ef349f31002315fcca", + "createdAt": "2019-03-07T22:22:26.829Z", + "updatedAt": "2019-03-07T22:22:26.829Z", + "activeLoan": { + "_id": "5c826c1f2e75f40023618147", + "requestedBy": "5c815595349f31002315fccf", + "requestedAt": "2019-03-08T13:20:31.145Z", + "estimatedReturnDate": "2019-03-22T18:05:35.551Z", + "loanDate": "2019-03-08T18:05:35.551Z", + "requestedByName": "Daivid Vasconcelos Leal", + "requestedByState": "5a107a691592ca19f7b4a860", + "requestedByCity": "Paulista" + }, + "gameData": { + "_id": "5c81997d349f31002315fd09", + "id": 55174, + "aggregated_rating": 63, + "cover": { + "id": 34441, + "height": 426, + "image_id": "w1higiwm5juqyprhn9ct", + "width": 843 + }, + "first_release_date": "2017-11-02T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + }, + { + "id": 4, + "name": "Split screen", + "slug": "split-screen" + } + ], + "genres": [ + { + "id": 7, + "name": "Music", + "slug": "music" + }, + { + "id": 14, + "name": "Sport", + "slug": "sport" + } + ], + "name": "Super Beat Sports", + "summary": "A rhythm sports game for Switch.", + "formattedReleaseDate": "02/11/2017" + } + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/loan/library_response_one_platform_success.json b/app/src/debug/assets/mockjson/library/loan/library_response_one_platform_success.json new file mode 100644 index 00000000..5a466ad3 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/loan/library_response_one_platform_success.json @@ -0,0 +1,76 @@ +{ + "data": { + "_id": "5c66f80a9321750023d99987", + "id": 22342, + "aggregated_rating": 42.5, + "aggregated_rating_count": 2, + "cover": { + "id": 16570, + "height": 913, + "image_id": "o0qarlntb9mwnquavfqn", + "width": 640 + }, + "first_release_date": "2005-11-16T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + }, + { + "id": 3, + "name": "Co-operative", + "slug": "co-operative" + } + ], + "genres": [ + { + "id": 14, + "name": "Sport", + "slug": "sport" + } + ], + "name": "Jogo XPTO", + "screenshots": [ + { + "id": 106461, + "height": 720, + "image_id": "dnpqjrudpolxqso4xfz0", + "width": 1280 + } + ], + "slug": "fifa-06-road-to-fifa-world-cup", + "summary": "You can experience the excitement of international soccer competition in FIFA 06. Extensive coaching options give you the opportunity to take control of all of your players on the pitch and determine their formation and strategy. FIFA 06 offers game modes ranging from a tournament to individual skill games. You can also play with real players from famous international teams from around the world. Multiplayer modes let you challenge other gamers.", + "url": "https://www.igdb.com/games/fifa-06-road-to-fifa-world-cup", + "formattedReleaseDate": "16/11/2005", + "createdBy": "5c58603ff8e6ef002376a5d2", + "videos": [], + "createdAt": "2019-02-15T17:34:02.039Z", + "updatedAt": "2019-02-15T17:34:02.039Z", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c891051624e3f0023d3a5ac", + "owner": "5c815595349f31002315fccf", + "ownerName": "Daivid Vasconcelos Leal", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Paulista" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/loan/library_response_success.json b/app/src/debug/assets/mockjson/library/loan/library_response_success.json new file mode 100644 index 00000000..39510e25 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/loan/library_response_success.json @@ -0,0 +1,41 @@ +{ + "data": { + "_id": "5c66f80a9321750023d99987", + "title": "Jogo XPTO", + "createdBy": "5c58603ff8e6ef002376a5d2", + "createdAt": "2019-02-15T17:34:02.039Z", + "updatedAt": "2019-02-15T17:34:02.039Z", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c66f81d9321750023d99988", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "John Doe", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaXbox360": [ + { + "_id": "5c66f81d9321750023d99988", + "owner": "5c58603ff8e6ef002376a5d2", + "ownerName": "John Doe", + "ownerState": "5a107a691592ca19f7b4a861", + "ownerCity": "Campinas do Piauí" + } + ], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 2, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0, + "game_modes": [], + "genres": [], + "screenshots": [], + "videos": [] + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/library/loan/perform_loan_success.json b/app/src/debug/assets/mockjson/library/loan/perform_loan_success.json new file mode 100644 index 00000000..79ca0fd4 --- /dev/null +++ b/app/src/debug/assets/mockjson/library/loan/perform_loan_success.json @@ -0,0 +1,25 @@ +{ + "message": [ + "Empréstimo salvo" + ], + "data": { + "requestedAt": "2019-02-19T13:43:26.539Z", + "_id": "5c6c08f42ec12a00236a4e51", + "media": { + "_id": "5c66fc8f9321750023d99992", + "platform": "XBOXONE" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "name": "YARA" + }, + "game": { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015" + } + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/delete_success.json b/app/src/debug/assets/mockjson/loadmygames/delete_success.json new file mode 100644 index 00000000..cc73dbaa --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/delete_success.json @@ -0,0 +1,20 @@ +{ + "message": [ + "Mídia removida" + ], + "data": { + "active": true, + "_id": "5c8910cb624e3f0023d3a5b2", + "game": { + "_id": "5c816449349f31002315fced", + "name": "FIFA Street" + }, + "platform": "PS4", + "owner": { + "_id": "5c815595349f31002315fccf", + "name": "Daivid Vasconcelos Leal" + }, + "createdAt": "2019-03-13T14:16:43.990Z", + "updatedAt": "2019-03-13T14:16:43.990Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/game_register_media_success.json b/app/src/debug/assets/mockjson/loadmygames/game_register_media_success.json new file mode 100644 index 00000000..d0c8d560 --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/game_register_media_success.json @@ -0,0 +1,10 @@ +{ + "_id": "5c3cb881098fab0023f6b0d5", + "title": "Space Invaders", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-14T16:27:45.355Z", + "updatedAt": "2019-01-14T16:27:45.355Z" +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/load_my_games_disabled_success.json b/app/src/debug/assets/mockjson/loadmygames/load_my_games_disabled_success.json new file mode 100644 index 00000000..01b68f8a --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/load_my_games_disabled_success.json @@ -0,0 +1,141 @@ +{ + "data": { + "list": [ + { + "_id": "5c891051624e3f0023d3a5ac", + "platform": "PS4", + "activeLoan": { + "_id": "5c89549b33610c00237a68a4", + "requestedAt": "2019-03-13T19:06:03.501Z" + }, + "gameData": { + "_id": "5c816b27349f31002315fcf0", + "name": "TEST" + }, + "active": false + }, + { + "_id": "5c891084624e3f0023d3a5ae", + "platform": "PS4", + "activeLoan": { + "_id": "5c891104624e3f0023d3a5b5", + "requestedAt": "2019-03-13T14:17:40.741Z" + }, + "gameData": { + "_id": "5c8255c92e75f40023618138", + "name": "FIFA 09" + }, + "active": false + }, + { + "_id": "5c891092624e3f0023d3a5af", + "platform": "PS4", + "activeLoan": { + "_id": "5c891110624e3f0023d3a5b6", + "requestedAt": "2019-03-13T14:17:52.365Z" + }, + "gameData": { + "_id": "5c7938f1ef995f00239a0cfe", + "name": "FIFA 12" + }, + "active": false + }, + { + "_id": "5c8910a1624e3f0023d3a5b0", + "platform": "PS4", + "activeLoan": { + "_id": "5c891116624e3f0023d3a5b7", + "requestedAt": "2019-03-13T14:17:58.737Z" + }, + "gameData": { + "_id": "5c7939e7ef995f00239a0d00", + "name": "FIFA 13" + }, + "active": false + }, + { + "_id": "5c8252af2e75f40023618134", + "platform": "PS4", + "activeLoan": { + "_id": "5c8267f02e75f40023618142", + "requestedAt": "2019-03-08T13:02:40.192Z", + "loanDate": "2019-03-08T14:47:04.846Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + }, + "active": false + }, + { + "_id": "5c8910bf624e3f0023d3a5b1", + "platform": "XBOX360", + "activeLoan": { + "_id": "5c891120624e3f0023d3a5b8", + "requestedAt": "2019-03-13T14:18:08.154Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + }, + "active": false + }, + { + "_id": "5c8910cb624e3f0023d3a5b2", + "platform": "PS4", + "activeLoan": { + "_id": "5c891126624e3f0023d3a5b9", + "requestedAt": "2019-03-13T14:18:14.620Z" + }, + "gameData": { + "_id": "5c816449349f31002315fced", + "name": "FIFA Street" + }, + "active": false + }, + { + "_id": "5c8256162e75f40023618139", + "platform": "PS4", + "activeLoan": { + "_id": "5c825ead2e75f4002361813b", + "requestedAt": "2019-03-08T12:23:09.786Z", + "loanDate": "2019-03-08T14:48:22.479Z" + }, + "gameData": { + "_id": "5c8197b6349f31002315fd08", + "name": "Super Meat Boy" + }, + "active": false + }, + { + "_id": "5c819031349f31002315fcff", + "platform": "PS4", + "activeLoan": { + "_id": "5c82531a2e75f40023618136", + "requestedAt": "2019-03-08T11:33:46.921Z", + "loanDate": "2019-03-08T11:33:55.453Z" + }, + "gameData": { + "_id": "5c8162a1349f31002315fce9", + "name": "The Amazing Spider-Man" + }, + "active": false + }, + { + "_id": "5c81598e349f31002315fcd6", + "platform": "PS4", + "activeLoan": { + "_id": "5c816317349f31002315fceb", + "requestedAt": "2019-03-07T18:29:43.722Z", + "loanDate": "2019-03-07T19:26:37.548Z" + }, + "gameData": { + "_id": "5c66feafdf4b530023a72773", + "name": "The Last of Us Remastered" + }, + "active": false + } + ], + "count": 20 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/load_my_games_enable_success.json b/app/src/debug/assets/mockjson/loadmygames/load_my_games_enable_success.json new file mode 100644 index 00000000..84281c8a --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/load_my_games_enable_success.json @@ -0,0 +1,20 @@ +{ + "message": [ + "Mídia removida" + ], + "data": { + "active": true, + "_id": "5c8278c72e75f40023618173", + "game": { + "_id": "5c8278c32e75f40023618172", + "name": "Asphalt 3D" + }, + "platform": "NINTENDOSWITCH", + "owner": { + "_id": "5c810617647c2c0023ccdb28", + "name": "Maherbson" + }, + "createdAt": "2019-03-08T14:14:31.453Z", + "updatedAt": "2019-03-08T14:14:31.453Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/load_my_games_remove_success.json b/app/src/debug/assets/mockjson/loadmygames/load_my_games_remove_success.json new file mode 100644 index 00000000..84281c8a --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/load_my_games_remove_success.json @@ -0,0 +1,20 @@ +{ + "message": [ + "Mídia removida" + ], + "data": { + "active": true, + "_id": "5c8278c72e75f40023618173", + "game": { + "_id": "5c8278c32e75f40023618172", + "name": "Asphalt 3D" + }, + "platform": "NINTENDOSWITCH", + "owner": { + "_id": "5c810617647c2c0023ccdb28", + "name": "Maherbson" + }, + "createdAt": "2019-03-08T14:14:31.453Z", + "updatedAt": "2019-03-08T14:14:31.453Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/load_my_games_success.json b/app/src/debug/assets/mockjson/loadmygames/load_my_games_success.json new file mode 100644 index 00000000..3752b0ff --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/load_my_games_success.json @@ -0,0 +1,141 @@ +{ + "data": { + "list": [ + { + "_id": "5c891051624e3f0023d3a5ac", + "platform": "PS4", + "activeLoan": { + "_id": "5c89549b33610c00237a68a4", + "requestedAt": "2019-03-13T19:06:03.501Z" + }, + "gameData": { + "_id": "5c816b27349f31002315fcf0", + "name": "TEST" + }, + "active": true + }, + { + "_id": "5c891084624e3f0023d3a5ae", + "platform": "PS4", + "activeLoan": { + "_id": "5c891104624e3f0023d3a5b5", + "requestedAt": "2019-03-13T14:17:40.741Z" + }, + "gameData": { + "_id": "5c8255c92e75f40023618138", + "name": "FIFA 09" + }, + "active": true + }, + { + "_id": "5c891092624e3f0023d3a5af", + "platform": "PS4", + "activeLoan": { + "_id": "5c891110624e3f0023d3a5b6", + "requestedAt": "2019-03-13T14:17:52.365Z" + }, + "gameData": { + "_id": "5c7938f1ef995f00239a0cfe", + "name": "FIFA 12" + }, + "active": true + }, + { + "_id": "5c8910a1624e3f0023d3a5b0", + "platform": "PS4", + "activeLoan": { + "_id": "5c891116624e3f0023d3a5b7", + "requestedAt": "2019-03-13T14:17:58.737Z" + }, + "gameData": { + "_id": "5c7939e7ef995f00239a0d00", + "name": "FIFA 13" + }, + "active": true + }, + { + "_id": "5c8252af2e75f40023618134", + "platform": "PS4", + "activeLoan": { + "_id": "5c8267f02e75f40023618142", + "requestedAt": "2019-03-08T13:02:40.192Z", + "loanDate": "2019-03-08T14:47:04.846Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + }, + "active": true + }, + { + "_id": "5c8910bf624e3f0023d3a5b1", + "platform": "XBOX360", + "activeLoan": { + "_id": "5c891120624e3f0023d3a5b8", + "requestedAt": "2019-03-13T14:18:08.154Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + }, + "active": true + }, + { + "_id": "5c8910cb624e3f0023d3a5b2", + "platform": "PS4", + "activeLoan": { + "_id": "5c891126624e3f0023d3a5b9", + "requestedAt": "2019-03-13T14:18:14.620Z" + }, + "gameData": { + "_id": "5c816449349f31002315fced", + "name": "FIFA Street" + }, + "active": true + }, + { + "_id": "5c8256162e75f40023618139", + "platform": "PS4", + "activeLoan": { + "_id": "5c825ead2e75f4002361813b", + "requestedAt": "2019-03-08T12:23:09.786Z", + "loanDate": "2019-03-08T14:48:22.479Z" + }, + "gameData": { + "_id": "5c8197b6349f31002315fd08", + "name": "Super Meat Boy" + }, + "active": true + }, + { + "_id": "5c819031349f31002315fcff", + "platform": "PS4", + "activeLoan": { + "_id": "5c82531a2e75f40023618136", + "requestedAt": "2019-03-08T11:33:46.921Z", + "loanDate": "2019-03-08T11:33:55.453Z" + }, + "gameData": { + "_id": "5c8162a1349f31002315fce9", + "name": "The Amazing Spider-Man" + }, + "active": true + }, + { + "_id": "5c81598e349f31002315fcd6", + "platform": "PS4", + "activeLoan": { + "_id": "5c816317349f31002315fceb", + "requestedAt": "2019-03-07T18:29:43.722Z", + "loanDate": "2019-03-07T19:26:37.548Z" + }, + "gameData": { + "_id": "5c66feafdf4b530023a72773", + "name": "The Last of Us Remastered" + }, + "active": true + } + ], + "count": 20 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/load_my_games_success_after_delete.json b/app/src/debug/assets/mockjson/loadmygames/load_my_games_success_after_delete.json new file mode 100644 index 00000000..6e98e04a --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/load_my_games_success_after_delete.json @@ -0,0 +1,131 @@ +{ + "data": { + "list": [ + { + "_id": "5c891051624e3f0023d3a5ac", + "platform": "PS4", + "activeLoan": { + "_id": "5c89549b33610c00237a68a4", + "requestedAt": "2019-03-13T19:06:03.501Z" + }, + "gameData": { + "_id": "5c816b27349f31002315fcf0", + "name": "FIFA 06: Road to FIFA World Cup" + } + }, + { + "_id": "5c891084624e3f0023d3a5ae", + "platform": "PS4", + "activeLoan": { + "_id": "5c891104624e3f0023d3a5b5", + "requestedAt": "2019-03-13T14:17:40.741Z" + }, + "gameData": { + "_id": "5c8255c92e75f40023618138", + "name": "FIFA 09" + } + }, + { + "_id": "5c891092624e3f0023d3a5af", + "platform": "PS4", + "activeLoan": { + "_id": "5c891110624e3f0023d3a5b6", + "requestedAt": "2019-03-13T14:17:52.365Z" + }, + "gameData": { + "_id": "5c7938f1ef995f00239a0cfe", + "name": "FIFA 12" + } + }, + { + "_id": "5c8910a1624e3f0023d3a5b0", + "platform": "PS4", + "activeLoan": { + "_id": "5c891116624e3f0023d3a5b7", + "requestedAt": "2019-03-13T14:17:58.737Z" + }, + "gameData": { + "_id": "5c7939e7ef995f00239a0d00", + "name": "FIFA 13" + } + }, + { + "_id": "5c8252af2e75f40023618134", + "platform": "PS4", + "activeLoan": { + "_id": "5c8267f02e75f40023618142", + "requestedAt": "2019-03-08T13:02:40.192Z", + "loanDate": "2019-03-08T14:47:04.846Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + } + }, + { + "_id": "5c8910bf624e3f0023d3a5b1", + "platform": "XBOX360", + "activeLoan": { + "_id": "5c891120624e3f0023d3a5b8", + "requestedAt": "2019-03-13T14:18:08.154Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + } + }, + { + "_id": "5c8910cb624e3f0023d3a5b2", + "platform": "PS4", + "activeLoan": { + "_id": "5c891126624e3f0023d3a5b9", + "requestedAt": "2019-03-13T14:18:14.620Z" + }, + "gameData": { + "_id": "5c816449349f31002315fced", + "name": "FIFA Street" + } + }, + { + "_id": "5c8256162e75f40023618139", + "platform": "PS4", + "activeLoan": { + "_id": "5c825ead2e75f4002361813b", + "requestedAt": "2019-03-08T12:23:09.786Z", + "loanDate": "2019-03-08T14:48:22.479Z" + }, + "gameData": { + "_id": "5c8197b6349f31002315fd08", + "name": "Super Meat Boy" + } + }, + { + "_id": "5c819031349f31002315fcff", + "platform": "PS4", + "activeLoan": { + "_id": "5c82531a2e75f40023618136", + "requestedAt": "2019-03-08T11:33:46.921Z", + "loanDate": "2019-03-08T11:33:55.453Z" + }, + "gameData": { + "_id": "5c8162a1349f31002315fce9", + "name": "The Amazing Spider-Man" + } + }, + { + "_id": "5c81598e349f31002315fcd6", + "platform": "PS4", + "activeLoan": { + "_id": "5c816317349f31002315fceb", + "requestedAt": "2019-03-07T18:29:43.722Z", + "loanDate": "2019-03-07T19:26:37.548Z" + }, + "gameData": { + "_id": "5c66feafdf4b530023a72773", + "name": "The Last of Us Remastered" + } + } + ], + "count": 20 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/load_my_games_success_disabled.json b/app/src/debug/assets/mockjson/loadmygames/load_my_games_success_disabled.json new file mode 100644 index 00000000..01b68f8a --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/load_my_games_success_disabled.json @@ -0,0 +1,141 @@ +{ + "data": { + "list": [ + { + "_id": "5c891051624e3f0023d3a5ac", + "platform": "PS4", + "activeLoan": { + "_id": "5c89549b33610c00237a68a4", + "requestedAt": "2019-03-13T19:06:03.501Z" + }, + "gameData": { + "_id": "5c816b27349f31002315fcf0", + "name": "TEST" + }, + "active": false + }, + { + "_id": "5c891084624e3f0023d3a5ae", + "platform": "PS4", + "activeLoan": { + "_id": "5c891104624e3f0023d3a5b5", + "requestedAt": "2019-03-13T14:17:40.741Z" + }, + "gameData": { + "_id": "5c8255c92e75f40023618138", + "name": "FIFA 09" + }, + "active": false + }, + { + "_id": "5c891092624e3f0023d3a5af", + "platform": "PS4", + "activeLoan": { + "_id": "5c891110624e3f0023d3a5b6", + "requestedAt": "2019-03-13T14:17:52.365Z" + }, + "gameData": { + "_id": "5c7938f1ef995f00239a0cfe", + "name": "FIFA 12" + }, + "active": false + }, + { + "_id": "5c8910a1624e3f0023d3a5b0", + "platform": "PS4", + "activeLoan": { + "_id": "5c891116624e3f0023d3a5b7", + "requestedAt": "2019-03-13T14:17:58.737Z" + }, + "gameData": { + "_id": "5c7939e7ef995f00239a0d00", + "name": "FIFA 13" + }, + "active": false + }, + { + "_id": "5c8252af2e75f40023618134", + "platform": "PS4", + "activeLoan": { + "_id": "5c8267f02e75f40023618142", + "requestedAt": "2019-03-08T13:02:40.192Z", + "loanDate": "2019-03-08T14:47:04.846Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + }, + "active": false + }, + { + "_id": "5c8910bf624e3f0023d3a5b1", + "platform": "XBOX360", + "activeLoan": { + "_id": "5c891120624e3f0023d3a5b8", + "requestedAt": "2019-03-13T14:18:08.154Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + }, + "active": false + }, + { + "_id": "5c8910cb624e3f0023d3a5b2", + "platform": "PS4", + "activeLoan": { + "_id": "5c891126624e3f0023d3a5b9", + "requestedAt": "2019-03-13T14:18:14.620Z" + }, + "gameData": { + "_id": "5c816449349f31002315fced", + "name": "FIFA Street" + }, + "active": false + }, + { + "_id": "5c8256162e75f40023618139", + "platform": "PS4", + "activeLoan": { + "_id": "5c825ead2e75f4002361813b", + "requestedAt": "2019-03-08T12:23:09.786Z", + "loanDate": "2019-03-08T14:48:22.479Z" + }, + "gameData": { + "_id": "5c8197b6349f31002315fd08", + "name": "Super Meat Boy" + }, + "active": false + }, + { + "_id": "5c819031349f31002315fcff", + "platform": "PS4", + "activeLoan": { + "_id": "5c82531a2e75f40023618136", + "requestedAt": "2019-03-08T11:33:46.921Z", + "loanDate": "2019-03-08T11:33:55.453Z" + }, + "gameData": { + "_id": "5c8162a1349f31002315fce9", + "name": "The Amazing Spider-Man" + }, + "active": false + }, + { + "_id": "5c81598e349f31002315fcd6", + "platform": "PS4", + "activeLoan": { + "_id": "5c816317349f31002315fceb", + "requestedAt": "2019-03-07T18:29:43.722Z", + "loanDate": "2019-03-07T19:26:37.548Z" + }, + "gameData": { + "_id": "5c66feafdf4b530023a72773", + "name": "The Last of Us Remastered" + }, + "active": false + } + ], + "count": 20 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/load_my_games_success_second.json b/app/src/debug/assets/mockjson/loadmygames/load_my_games_success_second.json new file mode 100644 index 00000000..0d009754 --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/load_my_games_success_second.json @@ -0,0 +1,131 @@ +{ + "data": { + "list": [ + { + "_id": "5c891051624e3f0023d3a5ac", + "platform": "PS4", + "activeLoan": { + "_id": "5c89549b33610c00237a68a4", + "requestedAt": "2019-03-13T19:06:03.501Z" + }, + "gameData": { + "_id": "5c816b27349f31002315fcf0", + "name": "SECOND" + } + }, + { + "_id": "5c891084624e3f0023d3a5ae", + "platform": "PS4", + "activeLoan": { + "_id": "5c891104624e3f0023d3a5b5", + "requestedAt": "2019-03-13T14:17:40.741Z" + }, + "gameData": { + "_id": "5c8255c92e75f40023618138", + "name": "FIFA 09" + } + }, + { + "_id": "5c891092624e3f0023d3a5af", + "platform": "PS4", + "activeLoan": { + "_id": "5c891110624e3f0023d3a5b6", + "requestedAt": "2019-03-13T14:17:52.365Z" + }, + "gameData": { + "_id": "5c7938f1ef995f00239a0cfe", + "name": "FIFA 12" + } + }, + { + "_id": "5c8910a1624e3f0023d3a5b0", + "platform": "PS4", + "activeLoan": { + "_id": "5c891116624e3f0023d3a5b7", + "requestedAt": "2019-03-13T14:17:58.737Z" + }, + "gameData": { + "_id": "5c7939e7ef995f00239a0d00", + "name": "FIFA 13" + } + }, + { + "_id": "5c8252af2e75f40023618134", + "platform": "PS4", + "activeLoan": { + "_id": "5c8267f02e75f40023618142", + "requestedAt": "2019-03-08T13:02:40.192Z", + "loanDate": "2019-03-08T14:47:04.846Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + } + }, + { + "_id": "5c8910bf624e3f0023d3a5b1", + "platform": "XBOX360", + "activeLoan": { + "_id": "5c891120624e3f0023d3a5b8", + "requestedAt": "2019-03-13T14:18:08.154Z" + }, + "gameData": { + "_id": "5c8252a72e75f40023618133", + "name": "FIFA 18" + } + }, + { + "_id": "5c8910cb624e3f0023d3a5b2", + "platform": "PS4", + "activeLoan": { + "_id": "5c891126624e3f0023d3a5b9", + "requestedAt": "2019-03-13T14:18:14.620Z" + }, + "gameData": { + "_id": "5c816449349f31002315fced", + "name": "FIFA Street" + } + }, + { + "_id": "5c8256162e75f40023618139", + "platform": "PS4", + "activeLoan": { + "_id": "5c825ead2e75f4002361813b", + "requestedAt": "2019-03-08T12:23:09.786Z", + "loanDate": "2019-03-08T14:48:22.479Z" + }, + "gameData": { + "_id": "5c8197b6349f31002315fd08", + "name": "Super Meat Boy" + } + }, + { + "_id": "5c819031349f31002315fcff", + "platform": "PS4", + "activeLoan": { + "_id": "5c82531a2e75f40023618136", + "requestedAt": "2019-03-08T11:33:46.921Z", + "loanDate": "2019-03-08T11:33:55.453Z" + }, + "gameData": { + "_id": "5c8162a1349f31002315fce9", + "name": "The Amazing Spider-Man" + } + }, + { + "_id": "5c81598e349f31002315fcd6", + "platform": "PS4", + "activeLoan": { + "_id": "5c816317349f31002315fceb", + "requestedAt": "2019-03-07T18:29:43.722Z", + "loanDate": "2019-03-07T19:26:37.548Z" + }, + "gameData": { + "_id": "5c66feafdf4b530023a72773", + "name": "The Last of Us Remastered" + } + } + ], + "count": 20 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/register_media_deleted_success.json b/app/src/debug/assets/mockjson/loadmygames/register_media_deleted_success.json new file mode 100644 index 00000000..974bd75a --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/register_media_deleted_success.json @@ -0,0 +1,20 @@ +{ + "message": [ + "Mídia atualizada" + ], + "data": { + "active": false, + "_id": "5c93b77613ee2200238e15b8", + "game": { + "_id": "5c794f6e169826002349874b", + "name": "Anthem" + }, + "platform": "PS4", + "owner": { + "_id": "5c810617647c2c0023ccdb28", + "name": "Usuário" + }, + "createdAt": "2019-03-21T16:10:30.987Z", + "updatedAt": "2019-04-11T17:50:47.602Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/loadmygames/register_media_success.json b/app/src/debug/assets/mockjson/loadmygames/register_media_success.json new file mode 100644 index 00000000..d0c8d560 --- /dev/null +++ b/app/src/debug/assets/mockjson/loadmygames/register_media_success.json @@ -0,0 +1,10 @@ +{ + "_id": "5c3cb881098fab0023f6b0d5", + "title": "Space Invaders", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-14T16:27:45.355Z", + "updatedAt": "2019-01-14T16:27:45.355Z" +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/login/login_success.json b/app/src/debug/assets/mockjson/login/login_success.json new file mode 100644 index 00000000..b0215270 --- /dev/null +++ b/app/src/debug/assets/mockjson/login/login_success.json @@ -0,0 +1,10 @@ +{ + "message": [ + "Login realizado" + ], + "data": { + "accessToken": "TOKEN", + "refreshToken": "REFRESH_TOKEN", + "tokenType": "JWT" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/models/response_media_3ds.json b/app/src/debug/assets/mockjson/models/response_media_3ds.json new file mode 100644 index 00000000..2e264da4 --- /dev/null +++ b/app/src/debug/assets/mockjson/models/response_media_3ds.json @@ -0,0 +1,21 @@ +{ + "message": [ + "Mídia salva" + ], + "data": { + "_id": "5c5348d8906fb50023e5072e", + "game": { + "_id": "5c5348d1906fb50023e5072d", + "title": "Doom" + }, + "platform": "NINTENDO3DS", + "owner": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-31T19:13:28.644Z", + "updatedAt": "2019-01-31T19:13:28.644Z" + } +} + + diff --git a/app/src/debug/assets/mockjson/models/response_media_ps4.json b/app/src/debug/assets/mockjson/models/response_media_ps4.json new file mode 100644 index 00000000..de7f4724 --- /dev/null +++ b/app/src/debug/assets/mockjson/models/response_media_ps4.json @@ -0,0 +1,21 @@ +{ + "message": [ + "Mídia salva" + ], + "data": { + "_id": "5c5348d8906fb50023e5072e", + "game": { + "_id": "5c5348d1906fb50023e5072d", + "title": "Doom" + }, + "platform": "PS4", + "owner": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-31T19:13:28.644Z", + "updatedAt": "2019-01-31T19:13:28.644Z" + } +} + + diff --git a/app/src/debug/assets/mockjson/models/response_media_switch.json b/app/src/debug/assets/mockjson/models/response_media_switch.json new file mode 100644 index 00000000..f970d717 --- /dev/null +++ b/app/src/debug/assets/mockjson/models/response_media_switch.json @@ -0,0 +1,19 @@ +{ + "message": [ + "Mídia salva" + ], + "data": { + "_id": "5c58391b8b9dac0023853a14", + "platform": "NINTENDOSWITCH", + "game": { + "_id": "5c48dd54e07db9002375d5ab", + "title": "Contra III" + }, + "owner": { + "_id": "5c2d129dd957060023385a1b", + "name": "RWYEG" + }, + "createdAt": "2019-02-04T13:07:39.609Z", + "updatedAt": "2019-02-04T13:07:39.609Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/models/response_media_x360.json b/app/src/debug/assets/mockjson/models/response_media_x360.json new file mode 100644 index 00000000..1d037032 --- /dev/null +++ b/app/src/debug/assets/mockjson/models/response_media_x360.json @@ -0,0 +1,19 @@ +{ + "message": [ + "Mídia salva" + ], + "data": { + "_id": "5c5348f4906fb50023e50730", + "game": { + "_id": "5c5348ef906fb50023e5072f", + "title": "Space Invaders" + }, + "platform": "XBOX360", + "owner": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-31T19:13:56.491Z", + "updatedAt": "2019-01-31T19:13:56.491Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/myreservations/delete_my_reservation_success.json b/app/src/debug/assets/mockjson/myreservations/delete_my_reservation_success.json new file mode 100644 index 00000000..282582f7 --- /dev/null +++ b/app/src/debug/assets/mockjson/myreservations/delete_my_reservation_success.json @@ -0,0 +1,14 @@ +{ + "message": [ + "Empréstimo removido" + ], + "data": { + "_id": "5c9a481b2930710023e75ba0", + "media": "5c952a0a0c59e50023beec80", + "requestedBy": "5c815595349f31002315fccf", + "mediaOwner": "5c5dba8ccc06180023fd7df7", + "game": "5c93dee63e379400232111f4", + "mediaPlatform": "PS4", + "requestedAt": "2019-03-26T15:41:15.226Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/myreservations/detail/load_active_reservation.json b/app/src/debug/assets/mockjson/myreservations/detail/load_active_reservation.json new file mode 100644 index 00000000..6c8c3cae --- /dev/null +++ b/app/src/debug/assets/mockjson/myreservations/detail/load_active_reservation.json @@ -0,0 +1,63 @@ +{ + "message": [ + "Empréstimo encontrado" + ], + "data": { + "_id": "5c6c0bde2ec12a00236a4e52", + "requestedAt": "2019-02-19T13:43:26.539Z", + "media": { + "_id": "5c66fef9df4b530023a72774", + "platform": "PS4" + }, + "requestedBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES", + "email": "email@email.com" + }, + "mediaOwner": { + "_id": "5c179fa83b6274002239a00b", + "name": "FELIPE TREVISAN", + "email": "felipe.t.cadastros@gmail.com" + }, + "game": { + "_id": "5c66feafdf4b530023a72773", + "aggregated_rating": 97.4, + "cover": { + "id": 70754, + "height": 1500, + "image_id": "co1ile", + "width": 1062 + }, + "first_release_date": "2014-07-29T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + } + ], + "genres": [ + { + "id": 5, + "name": "Shooter", + "slug": "shooter" + }, + { + "id": 31, + "name": "Adventure", + "slug": "adventure" + } + ], + "name": "The Last of Us Remastered", + "summary": "Winner of over 200 game of the year awards, The Last of Us has been remastered for the PlayStation®4. Now featuring higher resolution character models, improved shadows and lighting, in addition to several other gameplay improvements. \n \nAbandoned cities reclaimed by nature. A population decimated by a modern plague. Survivors are killing each other for food, weapons whatever they can get their hands on. Joel, a brutal survivor, and Ellie, a brave young teenage girl who is wise beyond her years, must work together if they hope to survive their journey across the US. \n \nThe Last of Us: Remastered includes the Abandoned Territories Map Pack, Reclaimed Territories Map Pack, and the critically acclaimed The Last of Us: Left Behind Single Player campaign. \n \nPS4 PRO ENHANCED: \n- PS4 Pro HD \n- Dynamic 4K Gaming \n- Greater Draw Distance \n- Visual FX \n- Vivid Textures \n- Deep Shadows \n- High Fidelity Assets \n- HDR", + "formattedReleaseDate": "29/07/2014" + }, + "estimatedReturnDate": "2019-03-06T18:44:58.540Z", + "loanDate": "2019-02-20T18:44:58.540Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/myreservations/detail/load_expired_reservation.json b/app/src/debug/assets/mockjson/myreservations/detail/load_expired_reservation.json new file mode 100644 index 00000000..85de7179 --- /dev/null +++ b/app/src/debug/assets/mockjson/myreservations/detail/load_expired_reservation.json @@ -0,0 +1,63 @@ +{ + "message": [ + "Empréstimo encontrado" + ], + "data": { + "_id": "5c6c0bde2ec12a00236a4e52", + "requestedAt": "2019-02-19T13:43:26.539Z", + "media": { + "_id": "5c66fef9df4b530023a72774", + "platform": "PS4" + }, + "requestedBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES", + "email": "email@email.com" + }, + "mediaOwner": { + "_id": "5c179fa83b6274002239a00b", + "name": "FELIPE TREVISAN", + "email": "felipe.t.cadastros@gmail.com" + }, + "game": { + "_id": "5c66feafdf4b530023a72773", + "aggregated_rating": 97.4, + "cover": { + "id": 70754, + "height": 1500, + "image_id": "co1ile", + "width": 1062 + }, + "first_release_date": "2014-07-29T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + } + ], + "genres": [ + { + "id": 5, + "name": "Shooter", + "slug": "shooter" + }, + { + "id": 31, + "name": "Adventure", + "slug": "adventure" + } + ], + "name": "The Last of Us Remastered", + "summary": "Winner of over 200 game of the year awards, The Last of Us has been remastered for the PlayStation®4. Now featuring higher resolution character models, improved shadows and lighting, in addition to several other gameplay improvements. \n \nAbandoned cities reclaimed by nature. A population decimated by a modern plague. Survivors are killing each other for food, weapons whatever they can get their hands on. Joel, a brutal survivor, and Ellie, a brave young teenage girl who is wise beyond her years, must work together if they hope to survive their journey across the US. \n \nThe Last of Us: Remastered includes the Abandoned Territories Map Pack, Reclaimed Territories Map Pack, and the critically acclaimed The Last of Us: Left Behind Single Player campaign. \n \nPS4 PRO ENHANCED: \n- PS4 Pro HD \n- Dynamic 4K Gaming \n- Greater Draw Distance \n- Visual FX \n- Vivid Textures \n- Deep Shadows \n- High Fidelity Assets \n- HDR", + "formattedReleaseDate": "29/07/2014" + }, + "estimatedReturnDate": "2019-02-06T18:44:58.540Z", + "loanDate": "2019-01-20T18:44:58.540Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/myreservations/detail/load_pending_reservation.json b/app/src/debug/assets/mockjson/myreservations/detail/load_pending_reservation.json new file mode 100644 index 00000000..5468cd81 --- /dev/null +++ b/app/src/debug/assets/mockjson/myreservations/detail/load_pending_reservation.json @@ -0,0 +1,61 @@ +{ + "message": [ + "Empréstimo encontrado" + ], + "data": { + "_id": "5c6c0bde2ec12a00236a4e52", + "requestedAt": "2019-02-19T13:43:26.539Z", + "media": { + "_id": "5c66fef9df4b530023a72774", + "platform": "PS4" + }, + "requestedBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES", + "email": "email@email.com" + }, + "mediaOwner": { + "_id": "5c179fa83b6274002239a00b", + "name": "FELIPE TREVISAN", + "email": "felipe.t.cadastros@gmail.com" + }, + "game": { + "_id": "5c66feafdf4b530023a72773", + "aggregated_rating": 97.4, + "cover": { + "id": 70754, + "height": 1500, + "image_id": "co1ile", + "width": 1062 + }, + "first_release_date": "2014-07-29T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + } + ], + "genres": [ + { + "id": 5, + "name": "Shooter", + "slug": "shooter" + }, + { + "id": 31, + "name": "Adventure", + "slug": "adventure" + } + ], + "name": "The Last of Us Remastered", + "summary": "Winner of over 200 game of the year awards, The Last of Us has been remastered for the PlayStation®4. Now featuring higher resolution character models, improved shadows and lighting, in addition to several other gameplay improvements. \n \nAbandoned cities reclaimed by nature. A population decimated by a modern plague. Survivors are killing each other for food, weapons whatever they can get their hands on. Joel, a brutal survivor, and Ellie, a brave young teenage girl who is wise beyond her years, must work together if they hope to survive their journey across the US. \n \nThe Last of Us: Remastered includes the Abandoned Territories Map Pack, Reclaimed Territories Map Pack, and the critically acclaimed The Last of Us: Left Behind Single Player campaign. \n \nPS4 PRO ENHANCED: \n- PS4 Pro HD \n- Dynamic 4K Gaming \n- Greater Draw Distance \n- Visual FX \n- Vivid Textures \n- Deep Shadows \n- High Fidelity Assets \n- HDR", + "formattedReleaseDate": "29/07/2014" + } + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/myreservations/load_my_reservations_success.json b/app/src/debug/assets/mockjson/myreservations/load_my_reservations_success.json new file mode 100644 index 00000000..e8d92dcc --- /dev/null +++ b/app/src/debug/assets/mockjson/myreservations/load_my_reservations_success.json @@ -0,0 +1,239 @@ +{ + "data": { + "list": [ + { + "_id": "654847", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "cvcvbb", + "platform": "PS4" + }, + "requestedBy": { + "_id": "gffgxvfnvc", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c1ab15c7c0f4f00ncnbncxn2272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "game": { + "_id": "nxcnxcvncvxnxvc", + "name": "Eeee" + } + }, + { + "_id": "5c6ab844a1826b0023ed7b61", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c65d5a8860df20023ec848a", + "platform": "PS4" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "game": { + "_id": "5c65d598860df20023ec8489", + "name": "culpa de yara" + }, + "estimatedReturnDate": "2019-03-06T23:44:48.976Z", + "loanDate": "2019-02-20T23:44:48.976Z" + }, + { + "_id": "5c6aba46a1826b0023ed7b62", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c65d38c860df20023ec8486", + "platform": "PS4" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "game": { + "_id": "5c65d298860df20023ec8484", + "name": "o jogo da vida" + } + }, + { + "_id": "5c6abcfba1826b0023ed7b63", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c65cae7860df20023ec8476", + "platform": "NINTENDOSWITCH" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "game": { + "_id": "5c65cae5860df20023ec8475", + "name": "jhv,jhv" + }, + "estimatedReturnDate": "2019-03-07T14:27:13.816Z", + "loanDate": "2019-02-21T14:27:13.816Z" + }, + { + "_id": "5c6ac1fda1826b0023ed7b64", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c646133352d58002358f368", + "platform": "PS3" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "game": { + "_id": "5c64612f352d58002358f367", + "name": "😉😍🙂😎" + }, + "estimatedReturnDate": "2019-03-07T12:40:52.319Z", + "loanDate": "2019-02-21T12:40:52.319Z" + }, + { + "_id": "5c6ac222a1826b0023ed7b65", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c66fc989321750023d99993", + "platform": "NINTENDOSWITCH" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "email": "yara.taciane.d.paula@concrete.com.br", + "name": "YARA" + }, + "game": { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015" + } + }, + { + "_id": "5c6b13d331b11e002320e0b1", + "requestedAt": "2019-02-18T16:33:14.959Z", + "media": { + "_id": "5c589edbf8e6ef002376a5f0", + "platform": "XBOXONE" + }, + "requestedBy": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c2d129dd957060023385a1b", + "email": "email2@email.com", + "name": "RWYEG" + }, + "game": { + "_id": "5c589ed4f8e6ef002376a5ef", + "name": "PES 2019" + } + }, + { + "_id": "5c6b198041437d00236a6333", + "requestedAt": "2019-02-18T19:26:56.127Z", + "media": { + "_id": "5c66f3fe9321750023d99983", + "platform": "XBOX360" + }, + "requestedBy": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "email": "yara.taciane.d.paula@concrete.com.br", + "name": "YARA" + }, + "game": { + "_id": "5c66f3fb9321750023d99982", + "name": "JOGO GRANDE" + }, + "estimatedReturnDate": "2019-03-07T19:06:03.564Z", + "loanDate": "2019-02-21T19:06:03.564Z" + }, + { + "_id": "5c6b19e041437d00236a6334", + "requestedAt": "2019-02-18T19:26:56.127Z", + "media": { + "_id": "5c66fc829321750023d99991", + "platform": "XBOX360" + }, + "requestedBy": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "email": "yara.taciane.d.paula@concrete.com.br", + "name": "YARA" + }, + "game": { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015" + }, + "estimatedReturnDate": "2019-03-07T19:35:25.615Z", + "loanDate": "2019-02-21T19:35:25.615Z" + }, + { + "_id": "5c6bfa3dd785b6002370ddf4", + "requestedAt": "2019-02-19T12:39:29.879Z", + "media": { + "_id": "5c66fc6a9321750023d9998f", + "platform": "PS3" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "email": "yara.taciane.d.paula@concrete.com.br", + "name": "YARA" + }, + "game": { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015" + }, + "estimatedReturnDate": "2019-03-07T19:35:54.487Z", + "loanDate": "2019-02-21T19:35:54.487Z" + } + ], + "count": 66 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/myreservations/load_my_reservations_success_after_remove.json b/app/src/debug/assets/mockjson/myreservations/load_my_reservations_success_after_remove.json new file mode 100644 index 00000000..04d46d3d --- /dev/null +++ b/app/src/debug/assets/mockjson/myreservations/load_my_reservations_success_after_remove.json @@ -0,0 +1,217 @@ +{ + "data": { + "list": [ + { + "_id": "5c6ab844a1826b0023ed7b61", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c65d5a8860df20023ec848a", + "platform": "PS4" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "game": { + "_id": "5c65d598860df20023ec8489", + "name": "culpa de yara" + }, + "estimatedReturnDate": "2019-03-06T23:44:48.976Z", + "loanDate": "2019-02-20T23:44:48.976Z" + }, + { + "_id": "5c6aba46a1826b0023ed7b62", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c65d38c860df20023ec8486", + "platform": "PS4" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "game": { + "_id": "5c65d298860df20023ec8484", + "name": "o jogo da vida" + } + }, + { + "_id": "5c6abcfba1826b0023ed7b63", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c65cae7860df20023ec8476", + "platform": "NINTENDOSWITCH" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "game": { + "_id": "5c65cae5860df20023ec8475", + "name": "jhv,jhv" + }, + "estimatedReturnDate": "2019-03-07T14:27:13.816Z", + "loanDate": "2019-02-21T14:27:13.816Z" + }, + { + "_id": "5c6ac1fda1826b0023ed7b64", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c646133352d58002358f368", + "platform": "PS3" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "game": { + "_id": "5c64612f352d58002358f367", + "name": "😉😍🙂😎" + }, + "estimatedReturnDate": "2019-03-07T12:40:52.319Z", + "loanDate": "2019-02-21T12:40:52.319Z" + }, + { + "_id": "5c6ac222a1826b0023ed7b65", + "requestedAt": "2019-02-18T13:45:29.390Z", + "media": { + "_id": "5c66fc989321750023d99993", + "platform": "NINTENDOSWITCH" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "email": "yara.taciane.d.paula@concrete.com.br", + "name": "YARA" + }, + "game": { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015" + } + }, + { + "_id": "5c6b13d331b11e002320e0b1", + "requestedAt": "2019-02-18T16:33:14.959Z", + "media": { + "_id": "5c589edbf8e6ef002376a5f0", + "platform": "XBOXONE" + }, + "requestedBy": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c2d129dd957060023385a1b", + "email": "email2@email.com", + "name": "RWYEG" + }, + "game": { + "_id": "5c589ed4f8e6ef002376a5ef", + "name": "PES 2019" + } + }, + { + "_id": "5c6b198041437d00236a6333", + "requestedAt": "2019-02-18T19:26:56.127Z", + "media": { + "_id": "5c66f3fe9321750023d99983", + "platform": "XBOX360" + }, + "requestedBy": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "email": "yara.taciane.d.paula@concrete.com.br", + "name": "YARA" + }, + "game": { + "_id": "5c66f3fb9321750023d99982", + "name": "JOGO GRANDE" + }, + "estimatedReturnDate": "2019-03-07T19:06:03.564Z", + "loanDate": "2019-02-21T19:06:03.564Z" + }, + { + "_id": "5c6b19e041437d00236a6334", + "requestedAt": "2019-02-18T19:26:56.127Z", + "media": { + "_id": "5c66fc829321750023d99991", + "platform": "XBOX360" + }, + "requestedBy": { + "_id": "5c1ab15c7c0f4f002272357f", + "name": "DAIVID V. LEAL", + "email": "daivid.v.leal@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "email": "yara.taciane.d.paula@concrete.com.br", + "name": "YARA" + }, + "game": { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015" + }, + "estimatedReturnDate": "2019-03-07T19:35:25.615Z", + "loanDate": "2019-02-21T19:35:25.615Z" + }, + { + "_id": "5c6bfa3dd785b6002370ddf4", + "requestedAt": "2019-02-19T12:39:29.879Z", + "media": { + "_id": "5c66fc6a9321750023d9998f", + "platform": "PS3" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "email": "yara.taciane.d.paula@concrete.com.br", + "name": "YARA" + }, + "game": { + "_id": "5c64438f352d58002358f362", + "name": "Fifa 2015" + }, + "estimatedReturnDate": "2019-03-07T19:35:54.487Z", + "loanDate": "2019-02-21T19:35:54.487Z" + } + ], + "count": 66 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/myreservations/myreservations_detail_success.json b/app/src/debug/assets/mockjson/myreservations/myreservations_detail_success.json new file mode 100644 index 00000000..bb963047 --- /dev/null +++ b/app/src/debug/assets/mockjson/myreservations/myreservations_detail_success.json @@ -0,0 +1,31 @@ +{ + "message": [ + "Empréstimo encontrado" + ], + "data": { + "_id": "5c6a97b8684dc800238b41ab", + "requestedAt": "2019-02-18T11:28:04.224Z", + "media": { + "_id": "5c66f81d9321750023d99988", + "platform": "PS4" + }, + "requestedBy": { + "_id": "5c18060442daa00022e856e1", + "name": "LEO MALKES", + "email": "leonardo.malkes@concrete.com.br" + }, + "mediaOwner": { + "_id": "5c58603ff8e6ef002376a5d2", + "email": "yara.taciane.d.paula@concrete.com.br", + "name": "YARA" + }, + "game": { + "_id": "5c66f80a9321750023d99987", + "name": "Eeee", + "game_modes": [], + "genres": [] + }, + "estimatedReturnDate": "2019-03-07T18:38:09.892Z", + "loanDate": "2019-02-21T18:38:09.892Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/profile/change_profile_success.json b/app/src/debug/assets/mockjson/profile/change_profile_success.json new file mode 100644 index 00000000..e5610a5f --- /dev/null +++ b/app/src/debug/assets/mockjson/profile/change_profile_success.json @@ -0,0 +1,11 @@ +{ + "message":[ + "Login realizado" + ], + "data":{ + "accessToken":"TOKEN", + "refreshToken":"REFRESH_TOKEN", + "tokenType":"JWT" + } + +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/profile/get_cities_success.json b/app/src/debug/assets/mockjson/profile/get_cities_success.json new file mode 100644 index 00000000..e21556cd --- /dev/null +++ b/app/src/debug/assets/mockjson/profile/get_cities_success.json @@ -0,0 +1,195 @@ +{ + "message": [ + "Estado encontrado" + ], + "data": { + "cities": [ + "Abreu e Lima", + "Afogados da Ingazeira", + "Afrânio", + "Agrestina", + "Água Preta", + "Águas Belas", + "Alagoinha", + "Aliança", + "Altinho", + "Amaraji", + "Angelim", + "Araçoiaba", + "Araripina", + "Arcoverde", + "Barra de Guabiraba", + "Barreiros", + "Belém de Maria", + "Belém de São Francisco", + "Belo Jardim", + "Betânia", + "Bezerros", + "Bodocó", + "Bom Conselho", + "Bom Jardim", + "Bonito", + "Brejão", + "Brejinho", + "Brejo da Madre de Deus", + "Buenos Aires", + "Buíque", + "Cabo de Santo Agostinho", + "Cabrobó", + "Cachoeirinha", + "Caetés", + "Calçado", + "Calumbi", + "Camaragibe", + "Camocim de São Félix", + "Camutanga", + "Canhotinho", + "Capoeiras", + "Carnaíba", + "Carnaubeira da Penha", + "Carpina", + "Caruaru", + "Casinhas", + "Catende", + "Cedro", + "Chã de Alegria", + "Chã Grande", + "Condado", + "Correntes", + "Cortês", + "Cumaru", + "Cupira", + "Custódia", + "Dormentes", + "Escada", + "Exu", + "Feira Nova", + "Fernando de Noronha", + "Ferreiros", + "Flores", + "Floresta", + "Frei Miguelinho", + "Gameleira", + "Garanhuns", + "Glória do Goitá", + "Goiana", + "Granito", + "Gravatá", + "Iati", + "Ibimirim", + "Ibirajuba", + "Igarassu", + "Iguaraci", + "Inajá", + "Ingazeira", + "Ipojuca", + "Ipubi", + "Itacuruba", + "Itaíba", + "Itamaracá", + "Itambé", + "Itapetim", + "Itapissuma", + "Itaquitinga", + "Jaboatão dos Guararapes", + "Jaqueira", + "Jataúba", + "Jatobá", + "João Alfredo", + "Joaquim Nabuco", + "Jucati", + "Jupi", + "Jurema", + "Lagoa do Carro", + "Lagoa do Itaenga", + "Lagoa do Ouro", + "Lagoa dos Gatos", + "Lagoa Grande", + "Lajedo", + "Limoeiro", + "Macaparana", + "Machados", + "Manari", + "Maraial", + "Mirandiba", + "Moreilândia", + "Moreno", + "Nazaré da Mata", + "Olinda", + "Orobó", + "Orocó", + "Ouricuri", + "Palmares", + "Palmeirina", + "Panelas", + "Paranatama", + "Parnamirim", + "Passira", + "Paudalho", + "Paulista", + "Pedra", + "Pesqueira", + "Petrolândia", + "Petrolina", + "Poção", + "Pombos", + "Primavera", + "Quipapá", + "Quixaba", + "Recife", + "Riacho das Almas", + "Ribeirão", + "Rio Formoso", + "Sairé", + "Salgadinho", + "Salgueiro", + "Saloá", + "Sanharó", + "Santa Cruz", + "Santa Cruz da Baixa Verde", + "Santa Cruz do Capibaribe", + "Santa Filomena", + "Santa Maria da Boa Vista", + "Santa Maria do Cambucá", + "Santa Terezinha", + "São Benedito do Sul", + "São Bento do Una", + "São Caitano", + "São João", + "São Joaquim do Monte", + "São José da Coroa Grande", + "São José do Belmonte", + "São José do Egito", + "São Lourenço da Mata", + "São Vicente Ferrer", + "Serra Talhada", + "Serrita", + "Sertânia", + "Sirinhaém", + "Solidão", + "Surubim", + "Tabira", + "Tacaimbó", + "Tacaratu", + "Tamandaré", + "Taquaritinga do Norte", + "Terezinha", + "Terra Nova", + "Timbaúba", + "Toritama", + "Tracunhaém", + "Trindade", + "Triunfo", + "Tupanatinga", + "Tuparetama", + "Venturosa", + "Verdejante", + "Vertente do Lério", + "Vertentes", + "Vicência", + "Vitória de Santo Antão", + "Xexéu" + ], + "_id": "5a107a691592ca19f7b4a860" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/profile/get_profile_error.json b/app/src/debug/assets/mockjson/profile/get_profile_error.json new file mode 100644 index 00000000..a5c533c3 --- /dev/null +++ b/app/src/debug/assets/mockjson/profile/get_profile_error.json @@ -0,0 +1,5 @@ +{ + "message": [ + "Dados inválidos para o campo 'Plataforma'." + ] +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/profile/get_profile_success.json b/app/src/debug/assets/mockjson/profile/get_profile_success.json new file mode 100644 index 00000000..0f8cc0b1 --- /dev/null +++ b/app/src/debug/assets/mockjson/profile/get_profile_success.json @@ -0,0 +1,19 @@ +{ + "message": [ + "Usuário salvo" + ], + "data": { + "_id": "123456789", + "name": "Damiana dos toró", + "email": "dragons@best.com", + "phone": "81 958742360", + "state": { + "_id": "5a107a691592ca19f7b4a860", + "initials": "PE", + "name": "Pernambuco" + }, + "city": "Recife", + "createdAt": "2019-01-17T21:36:04.584Z", + "updatedAt": "2019-01-17T21:36:04.584Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/profile/get_profile_success_another_user.json b/app/src/debug/assets/mockjson/profile/get_profile_success_another_user.json new file mode 100644 index 00000000..13e072c1 --- /dev/null +++ b/app/src/debug/assets/mockjson/profile/get_profile_success_another_user.json @@ -0,0 +1,19 @@ +{ + "message": [ + "Usuário salvo" + ], + "data": { + "_id": "123456789", + "name": "Damiana dos SOL", + "email": "dragons@best.com", + "phone": "81 958742360", + "state": { + "_id": "5a107a691592ca19f7b4a860", + "initials": "PE", + "name": "Ceará" + }, + "city": "Recife", + "createdAt": "2019-01-17T21:36:04.584Z", + "updatedAt": "2019-01-17T21:36:04.584Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/profile/get_states_success.json b/app/src/debug/assets/mockjson/profile/get_states_success.json new file mode 100644 index 00000000..6cdb9611 --- /dev/null +++ b/app/src/debug/assets/mockjson/profile/get_states_success.json @@ -0,0 +1,141 @@ +{ + "data": { + "list": [ + { + "_id": "5a107a681592ca19f7b4a851", + "initials": "AC", + "name": "Acre" + }, + { + "_id": "5a107a681592ca19f7b4a852", + "initials": "AL", + "name": "Alagoas" + }, + { + "_id": "5a107a681592ca19f7b4a854", + "initials": "AP", + "name": "Amapá" + }, + { + "_id": "5a107a681592ca19f7b4a853", + "initials": "AM", + "name": "Amazonas" + }, + { + "_id": "5a107a681592ca19f7b4a855", + "initials": "BA", + "name": "Bahia" + }, + { + "_id": "5a107a681592ca19f7b4a856", + "initials": "CE", + "name": "Ceará" + }, + { + "_id": "5a107a681592ca19f7b4a857", + "initials": "DF", + "name": "Distrito Federal" + }, + { + "_id": "5a107a681592ca19f7b4a858", + "initials": "ES", + "name": "Espírito Santo" + }, + { + "_id": "5a107a681592ca19f7b4a859", + "initials": "GO", + "name": "Goiás" + }, + { + "_id": "5a107a681592ca19f7b4a85a", + "initials": "MA", + "name": "Maranhão" + }, + { + "_id": "5a107a691592ca19f7b4a85d", + "initials": "MT", + "name": "Mato Grosso" + }, + { + "_id": "5a107a691592ca19f7b4a85c", + "initials": "MS", + "name": "Mato Grosso do Sul" + }, + { + "_id": "5a107a681592ca19f7b4a85b", + "initials": "MG", + "name": "Minas Gerais" + }, + { + "_id": "5a107a691592ca19f7b4a862", + "initials": "PR", + "name": "Paraná" + }, + { + "_id": "5a107a691592ca19f7b4a85f", + "initials": "PB", + "name": "Paraíba" + }, + { + "_id": "5a107a691592ca19f7b4a85e", + "initials": "PA", + "name": "Pará" + }, + { + "_id": "5a107a691592ca19f7b4a860", + "initials": "PE", + "name": "Pernambuco" + }, + { + "_id": "5a107a691592ca19f7b4a861", + "initials": "PI", + "name": "Piauí" + }, + { + "_id": "5a107a691592ca19f7b4a864", + "initials": "RN", + "name": "Rio Grande do Norte" + }, + { + "_id": "5a107a691592ca19f7b4a867", + "initials": "RS", + "name": "Rio Grande do Sul" + }, + { + "_id": "5a107a691592ca19f7b4a863", + "initials": "RJ", + "name": "Rio de Janeiro" + }, + { + "_id": "5a107a691592ca19f7b4a865", + "initials": "RO", + "name": "Rondônia" + }, + { + "_id": "5a107a691592ca19f7b4a866", + "initials": "RR", + "name": "Roraima" + }, + { + "_id": "5a107a691592ca19f7b4a868", + "initials": "SC", + "name": "Santa Catarina" + }, + { + "_id": "5a107a691592ca19f7b4a869", + "initials": "SE", + "name": "Sergipe" + }, + { + "_id": "5a107a691592ca19f7b4a86a", + "initials": "SP", + "name": "São Paulo" + }, + { + "_id": "5a107a691592ca19f7b4a86b", + "initials": "TO", + "name": "Tocantins" + } + ] + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/register/get_cities_success.json b/app/src/debug/assets/mockjson/register/get_cities_success.json new file mode 100644 index 00000000..e21556cd --- /dev/null +++ b/app/src/debug/assets/mockjson/register/get_cities_success.json @@ -0,0 +1,195 @@ +{ + "message": [ + "Estado encontrado" + ], + "data": { + "cities": [ + "Abreu e Lima", + "Afogados da Ingazeira", + "Afrânio", + "Agrestina", + "Água Preta", + "Águas Belas", + "Alagoinha", + "Aliança", + "Altinho", + "Amaraji", + "Angelim", + "Araçoiaba", + "Araripina", + "Arcoverde", + "Barra de Guabiraba", + "Barreiros", + "Belém de Maria", + "Belém de São Francisco", + "Belo Jardim", + "Betânia", + "Bezerros", + "Bodocó", + "Bom Conselho", + "Bom Jardim", + "Bonito", + "Brejão", + "Brejinho", + "Brejo da Madre de Deus", + "Buenos Aires", + "Buíque", + "Cabo de Santo Agostinho", + "Cabrobó", + "Cachoeirinha", + "Caetés", + "Calçado", + "Calumbi", + "Camaragibe", + "Camocim de São Félix", + "Camutanga", + "Canhotinho", + "Capoeiras", + "Carnaíba", + "Carnaubeira da Penha", + "Carpina", + "Caruaru", + "Casinhas", + "Catende", + "Cedro", + "Chã de Alegria", + "Chã Grande", + "Condado", + "Correntes", + "Cortês", + "Cumaru", + "Cupira", + "Custódia", + "Dormentes", + "Escada", + "Exu", + "Feira Nova", + "Fernando de Noronha", + "Ferreiros", + "Flores", + "Floresta", + "Frei Miguelinho", + "Gameleira", + "Garanhuns", + "Glória do Goitá", + "Goiana", + "Granito", + "Gravatá", + "Iati", + "Ibimirim", + "Ibirajuba", + "Igarassu", + "Iguaraci", + "Inajá", + "Ingazeira", + "Ipojuca", + "Ipubi", + "Itacuruba", + "Itaíba", + "Itamaracá", + "Itambé", + "Itapetim", + "Itapissuma", + "Itaquitinga", + "Jaboatão dos Guararapes", + "Jaqueira", + "Jataúba", + "Jatobá", + "João Alfredo", + "Joaquim Nabuco", + "Jucati", + "Jupi", + "Jurema", + "Lagoa do Carro", + "Lagoa do Itaenga", + "Lagoa do Ouro", + "Lagoa dos Gatos", + "Lagoa Grande", + "Lajedo", + "Limoeiro", + "Macaparana", + "Machados", + "Manari", + "Maraial", + "Mirandiba", + "Moreilândia", + "Moreno", + "Nazaré da Mata", + "Olinda", + "Orobó", + "Orocó", + "Ouricuri", + "Palmares", + "Palmeirina", + "Panelas", + "Paranatama", + "Parnamirim", + "Passira", + "Paudalho", + "Paulista", + "Pedra", + "Pesqueira", + "Petrolândia", + "Petrolina", + "Poção", + "Pombos", + "Primavera", + "Quipapá", + "Quixaba", + "Recife", + "Riacho das Almas", + "Ribeirão", + "Rio Formoso", + "Sairé", + "Salgadinho", + "Salgueiro", + "Saloá", + "Sanharó", + "Santa Cruz", + "Santa Cruz da Baixa Verde", + "Santa Cruz do Capibaribe", + "Santa Filomena", + "Santa Maria da Boa Vista", + "Santa Maria do Cambucá", + "Santa Terezinha", + "São Benedito do Sul", + "São Bento do Una", + "São Caitano", + "São João", + "São Joaquim do Monte", + "São José da Coroa Grande", + "São José do Belmonte", + "São José do Egito", + "São Lourenço da Mata", + "São Vicente Ferrer", + "Serra Talhada", + "Serrita", + "Sertânia", + "Sirinhaém", + "Solidão", + "Surubim", + "Tabira", + "Tacaimbó", + "Tacaratu", + "Tamandaré", + "Taquaritinga do Norte", + "Terezinha", + "Terra Nova", + "Timbaúba", + "Toritama", + "Tracunhaém", + "Trindade", + "Triunfo", + "Tupanatinga", + "Tuparetama", + "Venturosa", + "Verdejante", + "Vertente do Lério", + "Vertentes", + "Vicência", + "Vitória de Santo Antão", + "Xexéu" + ], + "_id": "5a107a691592ca19f7b4a860" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/register/get_states_success.json b/app/src/debug/assets/mockjson/register/get_states_success.json new file mode 100644 index 00000000..6cdb9611 --- /dev/null +++ b/app/src/debug/assets/mockjson/register/get_states_success.json @@ -0,0 +1,141 @@ +{ + "data": { + "list": [ + { + "_id": "5a107a681592ca19f7b4a851", + "initials": "AC", + "name": "Acre" + }, + { + "_id": "5a107a681592ca19f7b4a852", + "initials": "AL", + "name": "Alagoas" + }, + { + "_id": "5a107a681592ca19f7b4a854", + "initials": "AP", + "name": "Amapá" + }, + { + "_id": "5a107a681592ca19f7b4a853", + "initials": "AM", + "name": "Amazonas" + }, + { + "_id": "5a107a681592ca19f7b4a855", + "initials": "BA", + "name": "Bahia" + }, + { + "_id": "5a107a681592ca19f7b4a856", + "initials": "CE", + "name": "Ceará" + }, + { + "_id": "5a107a681592ca19f7b4a857", + "initials": "DF", + "name": "Distrito Federal" + }, + { + "_id": "5a107a681592ca19f7b4a858", + "initials": "ES", + "name": "Espírito Santo" + }, + { + "_id": "5a107a681592ca19f7b4a859", + "initials": "GO", + "name": "Goiás" + }, + { + "_id": "5a107a681592ca19f7b4a85a", + "initials": "MA", + "name": "Maranhão" + }, + { + "_id": "5a107a691592ca19f7b4a85d", + "initials": "MT", + "name": "Mato Grosso" + }, + { + "_id": "5a107a691592ca19f7b4a85c", + "initials": "MS", + "name": "Mato Grosso do Sul" + }, + { + "_id": "5a107a681592ca19f7b4a85b", + "initials": "MG", + "name": "Minas Gerais" + }, + { + "_id": "5a107a691592ca19f7b4a862", + "initials": "PR", + "name": "Paraná" + }, + { + "_id": "5a107a691592ca19f7b4a85f", + "initials": "PB", + "name": "Paraíba" + }, + { + "_id": "5a107a691592ca19f7b4a85e", + "initials": "PA", + "name": "Pará" + }, + { + "_id": "5a107a691592ca19f7b4a860", + "initials": "PE", + "name": "Pernambuco" + }, + { + "_id": "5a107a691592ca19f7b4a861", + "initials": "PI", + "name": "Piauí" + }, + { + "_id": "5a107a691592ca19f7b4a864", + "initials": "RN", + "name": "Rio Grande do Norte" + }, + { + "_id": "5a107a691592ca19f7b4a867", + "initials": "RS", + "name": "Rio Grande do Sul" + }, + { + "_id": "5a107a691592ca19f7b4a863", + "initials": "RJ", + "name": "Rio de Janeiro" + }, + { + "_id": "5a107a691592ca19f7b4a865", + "initials": "RO", + "name": "Rondônia" + }, + { + "_id": "5a107a691592ca19f7b4a866", + "initials": "RR", + "name": "Roraima" + }, + { + "_id": "5a107a691592ca19f7b4a868", + "initials": "SC", + "name": "Santa Catarina" + }, + { + "_id": "5a107a691592ca19f7b4a869", + "initials": "SE", + "name": "Sergipe" + }, + { + "_id": "5a107a691592ca19f7b4a86a", + "initials": "SP", + "name": "São Paulo" + }, + { + "_id": "5a107a691592ca19f7b4a86b", + "initials": "TO", + "name": "Tocantins" + } + ] + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/registerMedia/detail_game_success.json b/app/src/debug/assets/mockjson/registerMedia/detail_game_success.json new file mode 100644 index 00000000..af0922b2 --- /dev/null +++ b/app/src/debug/assets/mockjson/registerMedia/detail_game_success.json @@ -0,0 +1,76 @@ +{ + "data": { + "_id": "5c816b27349f31002315fcf0", + "id": 22342, + "aggregated_rating": 42.5, + "aggregated_rating_count": 2, + "cover": { + "id": 16570, + "height": 913, + "image_id": "o0qarlntb9mwnquavfqn", + "width": 640 + }, + "first_release_date": "2005-11-16T00:00:00.000Z", + "game_modes": [ + { + "id": 1, + "name": "Single player", + "slug": "single-player" + }, + { + "id": 2, + "name": "Multiplayer", + "slug": "multiplayer" + }, + { + "id": 3, + "name": "Co-operative", + "slug": "co-operative" + } + ], + "genres": [ + { + "id": 14, + "name": "Sport", + "slug": "sport" + } + ], + "name": "FIFA 06: Road to FIFA World Cup", + "screenshots": [ + { + "id": 106461, + "height": 720, + "image_id": "dnpqjrudpolxqso4xfz0", + "width": 1280 + } + ], + "slug": "fifa-06-road-to-fifa-world-cup", + "summary": "You can experience the excitement of international soccer competition in FIFA 06. Extensive coaching options give you the opportunity to take control of all of your players on the pitch and determine their formation and strategy. FIFA 06 offers game modes ranging from a tournament to individual skill games. You can also play with real players from famous international teams from around the world. Multiplayer modes let you challenge other gamers.", + "url": "https://www.igdb.com/games/fifa-06-road-to-fifa-world-cup", + "formattedReleaseDate": "16/11/2005", + "createdBy": "5c81593f349f31002315fcd4", + "videos": [], + "createdAt": "2019-03-07T19:04:07.729Z", + "updatedAt": "2019-03-07T19:04:07.729Z", + "mediaPs3": [], + "mediaPs4": [ + { + "_id": "5c891051624e3f0023d3a5ac", + "owner": "5c815595349f31002315fccf", + "ownerName": "Daivid Vasconcelos Leal", + "ownerState": "5a107a691592ca19f7b4a860", + "ownerCity": "Paulista" + } + ], + "mediaXbox360": [], + "mediaXboxOne": [], + "mediaNintendo3ds": [], + "mediaNintendoSwitch": [], + "mediaPs3Count": 0, + "mediaPs4Count": 1, + "mediaXbox360Count": 0, + "mediaXboxOneCount": 0, + "mediaNintendo3dsCount": 0, + "mediaNintendoSwitchCount": 0 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/registerMedia/game.json b/app/src/debug/assets/mockjson/registerMedia/game.json new file mode 100644 index 00000000..21d3400f --- /dev/null +++ b/app/src/debug/assets/mockjson/registerMedia/game.json @@ -0,0 +1,10 @@ +{ + "_id": "5c48dd54e07db9002375d5ab", + "title": "Contra III", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-23T21:32:04.829Z", + "updatedAt": "2019-01-23T21:32:04.829Z" +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/registerMedia/register_media_success.json b/app/src/debug/assets/mockjson/registerMedia/register_media_success.json new file mode 100644 index 00000000..aad91b6f --- /dev/null +++ b/app/src/debug/assets/mockjson/registerMedia/register_media_success.json @@ -0,0 +1,20 @@ +{ + "message": [ + "Mídia salva" + ], + "data": { + "active": true, + "_id": "5c4630bccd1df100236a6b2c", + "platform": "PS3", + "game": { + "_id": "5c3cb881098fab0023f6b0d5", + "title": "Battlefield V" + }, + "owner": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-21T20:51:08.405Z", + "updatedAt": "2019-01-21T20:51:08.405Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/registerMedia/remote_games_success.json b/app/src/debug/assets/mockjson/registerMedia/remote_games_success.json new file mode 100644 index 00000000..cb11f963 --- /dev/null +++ b/app/src/debug/assets/mockjson/registerMedia/remote_games_success.json @@ -0,0 +1,370 @@ +{ + "data": { + "list": [ + { + "id": 1070, + "aggregated_rating": 100, + "aggregated_rating_count": 1, + "category": 0, + "cover": { + "id": 69388, + "height": 561, + "image_id": "co1hjg", + "width": 800 + }, + "first_release_date": "1990-11-21T00:00:00.000Z", + "name": "Super Mario World", + "summary": "Super Mario World (known in Japan as Super Mario World: Super Mario Bros. 4) is a side-scrolling platformer developed by Nintendo EAD and published by Nintendo for the Super Nintendo Entertainment System on November 21, 1990 (in Japan), August 31, 1991 (in North America), and April 11, 1992 (in Europe). \n \nOne of the launch titles of the SNES (and bundled with early systems in North America), Super Mario World is the fifth main game in the Super Mario series. (starring Nintendo's mascot, Mario, and his brother, Luigi). The game follows both Mario brothers as they explore Dinosaur Land (known for its large amount of dinosaurs) to find and defeat the evil Koopa king Bowser (and his seven underlings, the Koopalings) while rescuing Princess Toadstool. \n \nAlong with new abilities (such as the \"Spin Jump\"), a new power-up (the \"Cape Feather\") and more obstacles, the game introduces dinosaur companions (known as Yoshi) that Mario and Luigi can ride. Yoshi, known for using their long tongues to snare and eat enemies, have become a fan-favorite among the series (giving them their own games and spin-offs, most notably this game's prequel). \n \nSpecial bundles of the SNES in 1994 included a compilation cartridge mixing Super Mario World with Super Mario All-Stars. The only difference in this version is a new sprite set for Luigi. The original game was later ported to the Game Boy Advance on February 11, 2002 as Super Mario World: Super Mario Advance 2. Along with a special version of the original Mario Bros., the port includes a variety of differences, including Luigi as a selectable character (who now has unique features, such as his floating jump from Super Mario Bros. 2), new voice acting, and the ability to save anywhere. The original game was also digitally re-released in Nintendo's Virtual Console platform for the Wii (on February 5, 2007) and Wii U (on April 26, 2013).", + "formattedReleaseDate": "21/11/1990" + }, + { + "id": 1067, + "category": 0, + "cover": { + "id": 65622, + "height": 600, + "image_id": "suassfx7mt3lpsctjlxw", + "width": 438 + }, + "first_release_date": "1988-09-01T00:00:00.000Z", + "name": "Super Mario Bros. 2", + "summary": "Mario’s back! Bigger and badder than before! This time it’s a fierce action-packed battle to free the land of Subcon from the curse of the evil Wart. It’s up to you, along with Mario, Luigi, Toad and the Princess, to fight your way through bizarre multi-level worlds and find him! This time you’ve got a brand new kind of power - plucking power - and now anything you find can be a weapon. But beware! You’ve never seen creatures like these! Shyguys and Tweeters! Ninji and Beezos! And you’ve never had an adventure like this! Only cunning and speed can save you now…", + "formattedReleaseDate": "01/09/1988" + }, + { + "id": 1079, + "aggregated_rating": 90, + "aggregated_rating_count": 10, + "category": 0, + "cover": { + "id": 1063, + "height": 464, + "image_id": "fcgiwb5fhmiyoil5xohy", + "width": 520 + }, + "first_release_date": "2011-11-03T00:00:00.000Z", + "name": "Super Mario 3D Land", + "summary": "Mario is once again out to beat Bowser in Super Mario 3D Land! The game features the well-known Mario playstyle that people all around the world love, but in 3D!", + "formattedReleaseDate": "03/11/2011" + }, + { + "id": 49877, + "aggregated_rating": 82, + "aggregated_rating_count": 1, + "category": 0, + "cover": { + "id": 27570, + "height": 1000, + "image_id": "iac6sxowktu93yke0hgh", + "width": 1000 + }, + "first_release_date": "1999-05-30T00:00:00.000Z", + "name": "Super Mario Bros. Deluxe", + "summary": "Bowser has once again taken over the Mushroom Kingdom, and it's up to Mario to put an end to his sinister reign. Battle Bowser's vile henchmen through 32 different levels - all taken directly from the 1985 classic! Then move on to collect special Red Coins and Yoshi Eggs in the Challenge Mode. Or face off against a friend and race through 8 competition courses in the all-new VS Mode! This time there's a lot more to do than just save a Princess, so get ready for a brick-smashin', pipe-warpin', turtle-stompin' good time!", + "formattedReleaseDate": "30/05/1999" + }, + { + "id": 1072, + "category": 0, + "cover": { + "id": 1071, + "height": 737, + "image_id": "oz4pynjbgos0vcyhylyi", + "width": 729 + }, + "first_release_date": "1994-03-31T00:00:00.000Z", + "name": "Wario Land: Super Mario Land 3", + "summary": "Hey! Things are really cookin' on Kitchen Island! Wario's got a scheme to steal the pirates' treasure so he can have his very own castle! You help Wario get the treasure by smashing into the the magic pots! Each pot changes him into Dragon Wario, Bull Wario, or Jet Wario! With each change comes new powers! \n \nDozens of enemies try to stop Wario, but you have the power to beat them! \n \nBe the bad guy! \n \nExplore the many exciting levels of Kitchen Island! \n \nBattery-backed memory saves your progress for many hours of fun!", + "formattedReleaseDate": "31/03/1994" + }, + { + "id": 16747, + "aggregated_rating": 90, + "aggregated_rating_count": 1, + "category": 0, + "cover": { + "id": 13963, + "height": 479, + "image_id": "zoachzirbptak6nwimgd", + "width": 483 + }, + "first_release_date": "2002-09-20T00:00:00.000Z", + "name": "Super Mario Advance 3: Yoshi's Island", + "summary": "Super Mario Advance 3 is a GBA remake for the SNES with the dinosaur Yoshi and his friends as main characters carrying Baby Mario and Luigi on their back. \n \nSuper Mario Advance is a four-part series for the GBA with Super Mario games of the NES and SNES era. The remakes came with adjusted graphics, sound and additional content. Each game of the series includes additionally the arcade-classic \"Mario Bros\" which can be played in multiplayer via link cable.", + "formattedReleaseDate": "20/09/2002" + }, + { + "id": 1069, + "category": 0, + "cover": { + "id": 1069, + "height": 500, + "image_id": "p9gyfxwavpmcibejrpiz", + "width": 486 + }, + "first_release_date": "1989-04-21T00:00:00.000Z", + "name": "Super Mario Land", + "summary": "Journey with Mario to a land of giant crabs, Koopa Troopas, flying stone heads and hungry sharks! \n \nTravel over land, in the air, and underwater. Mario makes his way through four treacherous worlds on his way to save the Princess!", + "formattedReleaseDate": "21/04/1989" + }, + { + "id": 358, + "category": 0, + "cover": { + "id": 65627, + "height": 600, + "image_id": "mrrnryomkk2hhmrwzk78", + "width": 438 + }, + "first_release_date": "1985-09-13T00:00:00.000Z", + "name": "Super Mario Bros.", + "summary": "Do you have what it takes to save the Mushroom Princess? You’ll have to think fast and move even faster to complete this quest! The Mushroom Princess is being held captive by the evil Koopa tribe of turtles. It’s up to you to rescue her from the clutches of the Koopa King before time runs out. But it won’t be easy. To get to the Princess, you’ll have to climb mountains, cross seas, avoid bottomless pits, fight off turtle soldiers and a host of black magic traps that only a Koopa King can devise. It’s another non-stop adventure from the Super Mario Bros.!", + "formattedReleaseDate": "13/09/1985" + }, + { + "id": 115276, + "category": 0, + "cover": { + "id": 71673, + "height": 1000, + "image_id": "co1jax", + "width": 750 + }, + "first_release_date": "2019-06-30T00:00:00.000Z", + "name": "Super Mario Maker 2", + "summary": "Build and play the Super Mario courses of your dreams! This sequel features a host of new tools and features—like slopes!", + "formattedReleaseDate": "30/06/2019" + }, + { + "id": 2332, + "aggregated_rating": 90, + "aggregated_rating_count": 2, + "category": 0, + "cover": { + "id": 40305, + "height": 730, + "image_id": "it2lmsv3nyj4neqoqbf5", + "width": 1000 + }, + "first_release_date": "1992-08-27T00:00:00.000Z", + "name": "Super Mario Kart", + "summary": "Super Mario Kart is a racing game for the Super Nintendo Entertainment System and the first game of the Mario Kart series, as well as the game that sets precedents to fictional kart racing genre. It was first released in 1992 and re-released in 1996 as a Player's Choice title. Part of this game is heavily based on another successful game, Super Mario World.", + "formattedReleaseDate": "27/08/1992" + }, + { + "id": 103339, + "aggregated_rating": 72.9090909090909, + "aggregated_rating_count": 12, + "category": 0, + "cover": { + "id": 69274, + "height": 600, + "image_id": "co1hga", + "width": 365 + }, + "first_release_date": "2018-10-05T00:00:00.000Z", + "name": "Super Mario Party", + "summary": "Inspired by the original Mario Party board game play, the beloved series is coming to Nintendo Switch with new mini-games and play styles that make use of the Joy-Con controllers. Super Mario Party includes features like character-exclusive Dice Blocks that add depth to players’ strategy. Up to four players take turns rolling the dice, and individually race across the board searching for Stars. In Toad’s Rec Room, new gameplay links two games and two Nintendo Switch systems for side-by-side fun. The game launched on Oct. 5, 2018.", + "formattedReleaseDate": "05/10/2018" + }, + { + "id": 1068, + "category": 0, + "cover": { + "id": 1059, + "height": 775, + "image_id": "ogguvec9vhrsml4uxqrg", + "width": 565 + }, + "first_release_date": "1988-10-03T00:00:00.000Z", + "name": "Super Mario Bros. 3", + "summary": "Super Mario Bros. 3 is a platform video game for the Nintendo Entertainment System (NES) video game console. Mario and Luigi embark on a quest to save Princess Toadstool and the rulers of seven different kingdoms from the antagonist Bowser and his children, the Koopalings. The player, as Mario or Luigi, is able to defeat enemies by stomping them or using items that bestow magical powers. Mario and Luigi are given a wider range of abilities than in previous Super Mario games, including flying or sliding down slopes. In addition, Super Mario Bros. 3 introduces numerous elements, such as new enemy characters and the use of a world map to transition between levels, that have reappeared in or have influenced subsequent Mario games.", + "formattedReleaseDate": "03/10/1988" + }, + { + "id": 26758, + "aggregated_rating": 96.7058823529412, + "aggregated_rating_count": 19, + "category": 0, + "cover": { + "id": 44025, + "height": 4252, + "image_id": "u4m45xwqdq8cuu4b9elq", + "width": 2718 + }, + "first_release_date": "2017-10-27T00:00:00.000Z", + "name": "Super Mario Odyssey", + "summary": "The game has Mario leaving the Mushroom Kingdom to reach an unknown open world-like setting, like Super Mario 64 and Super Mario Sunshine.", + "formattedReleaseDate": "27/10/2017" + }, + { + "id": 1080, + "aggregated_rating": 77.0833333333333, + "aggregated_rating_count": 13, + "category": 0, + "cover": { + "id": 1065, + "height": 534, + "image_id": "suosktmvzkynhlmizn2g", + "width": 600 + }, + "first_release_date": "2012-07-28T00:00:00.000Z", + "name": "New Super Mario Bros. 2", + "summary": "New Super Mario Bros. 2 is a traditional side-scrolling adventure game featuring Mario, Luigi and loads of other favorite characters from the popular Mario series. The game was created specifically as a pick-up-and-play experience that can be instantly enjoyed by players of all skill levels on the Nintendo 3DS system.", + "formattedReleaseDate": "28/07/2012" + }, + { + "id": 109457, + "aggregated_rating": 82.7777777777778, + "aggregated_rating_count": 11, + "category": 0, + "cover": { + "id": 69051, + "height": 2848, + "image_id": "co1ha3", + "width": 2067 + }, + "first_release_date": "2019-01-11T00:00:00.000Z", + "name": "New Super Mario Bros. U Deluxe", + "summary": "New Super Mario Bros. U including New Super Luigi U. for the Nintendo Switch!", + "formattedReleaseDate": "11/01/2019" + }, + { + "id": 1066, + "category": 0, + "cover": { + "id": 1062, + "height": 602, + "image_id": "j6vyifrkfpq9jinr2bek", + "width": 600 + }, + "first_release_date": "1986-05-03T00:00:00.000Z", + "name": "Super Mario Bros.: The Lost Levels", + "summary": "Super Mario Bros.: The Lost Levels is a true video game treasure.", + "formattedReleaseDate": "03/05/1986" + }, + { + "id": 26157, + "aggregated_rating": 67.8333333333333, + "aggregated_rating_count": 12, + "category": 0, + "cover": { + "id": 19223, + "height": 899, + "image_id": "rdte9wtobjyn7dt0l18s", + "width": 984 + }, + "first_release_date": "2016-12-01T00:00:00.000Z", + "name": "Super Mario Maker for Nintendo 3DS", + "summary": "Super Mario Maker for Nintendo 3DS features all the same tools as the original Wii U version but does not support online sharing. Instead it comes with 100 courses designed by Nintendo featuring special challenges. Also new is the ability of collaborating on unfinished courses locally.", + "formattedReleaseDate": "01/12/2016" + }, + { + "id": 67198, + "aggregated_rating": 76, + "aggregated_rating_count": 1, + "category": 0, + "cover": { + "id": 61335, + "height": 1000, + "image_id": "vieqzhasvntx8lsbx8tl", + "width": 1000 + }, + "first_release_date": "2017-12-21T00:00:00.000Z", + "name": "Arcade Archives VS. SUPER MARIO BROS.", + "summary": "VS. SUPER MARIO BROS. is an action game released in 1986 by Nintendo.", + "formattedReleaseDate": "21/12/2017" + }, + { + "id": 1071, + "category": 0, + "cover": { + "id": 1064, + "height": 586, + "image_id": "dcjo8ck4mtdbnukst2xo", + "width": 600 + }, + "first_release_date": "1992-10-21T00:00:00.000Z", + "name": "Super Mario Land 2: 6 Golden Coins", + "summary": "In his greatest Game Boy adventure, Mario faces off against his evil rival Wario, who has captured Mario Land and turned it into his private playground. \n \nTo toss Wario off his ill-gotten throne, Mario must search all-new worlds for the six golden coins that unlock the gate to Mario's castle. A mob of monsters, old and new, seek to stop him. Along the way, through 6 zones, Mario can nab Power Mushrooms, Super Stars and Fire Flowers for extra power. And if he eats the Magic Carrot, he'll turn into a high-flying hare. \n \nThe battery pack saves your game in progress in this biggest Game Boy Mario adventure yet.", + "formattedReleaseDate": "21/10/1992" + }, + { + "id": 8591, + "aggregated_rating": 76, + "aggregated_rating_count": 5, + "category": 0, + "cover": { + "id": 15721, + "height": 1372, + "image_id": "cpu69isowbcalwygdegr", + "width": 1500 + }, + "first_release_date": "2013-12-12T00:00:00.000Z", + "name": "Puzzle & Dragons Z + Puzzle & Dragons Super Mario Bros.", + "summary": "Two Puzzle & Dragons releases are combined into one for this North American release.", + "formattedReleaseDate": "12/12/2013" + }, + { + "id": 3350, + "aggregated_rating": 78.8181818181818, + "aggregated_rating_count": 13, + "category": 0, + "cover": { + "id": 70494, + "height": 1800, + "image_id": "co1ie6", + "width": 1270 + }, + "first_release_date": "2012-11-11T00:00:00.000Z", + "name": "Paper Mario: Sticker Star", + "summary": "On the day of the annual Sticker Fest, Bowser decides to pull a prank and scatters six Royal Stickers across the land. To retrieve these mysterious, magical stickers, which are now stuck onto Bowser and his underlings, Mario sets off on an adventure with Kersti, a sticker fairy, visiting prairies, deserts, forests, snowy mountains and volcanoes around the world.", + "formattedReleaseDate": "11/11/2012" + }, + { + "id": 85357, + "category": 0, + "cover": { + "id": 62129, + "height": 1373, + "image_id": "laza8xj7sngfqqu68fae", + "width": 1536 + }, + "first_release_date": "2015-05-08T00:00:00.000Z", + "name": "Puzzle & Dragons Z + Puzzle & Dragons: Super Mario Bros. Edition", + "summary": "Role-playing elements and match-three puzzle fun meet in Puzzle & Dragons Z + Puzzle & Dragons: Super Mario Bros. Edition. In a single package containing both games, explore dungeons, command monsters and master all types of elemental Orbs to defeat the enemy hordes!", + "formattedReleaseDate": "08/05/2015" + }, + { + "id": 2343, + "aggregated_rating": 90, + "aggregated_rating_count": 1, + "category": 0, + "cover": { + "id": 2406, + "height": 250, + "image_id": "m8sdu5wj1mcfhey2pe6u", + "width": 250 + }, + "first_release_date": "2001-07-21T00:00:00.000Z", + "name": "Mario Kart: Super Circuit", + "summary": "Classic Mario Kart action is back once again, this time in a colorful, lightning-fast game that you can take anywhere. Mario, Luigi, Peach, Toad, Wario, Yoshi and Bowser are all tearing up the track, tossing Koopa Shells and laying banana peels along the way. \n \nMario Kart Super Circuit puts your driving skills to the test on 40 tracks, each littered with wild weapons and obstacles. Choose to play as any of your favorite characters as you speed around classic and brand-new tracks. If you're feeling combative, try out the creative weaponry (mushrooms, bananas, thunder bolts, and stars) in Battle mode. Feel like making some friends eat your dust? No problem. Four players can compete in Mario Kart Super Circuit using only one Game Pak! If each player has a copy of the game, bonus features and new modes of play become available.", + "formattedReleaseDate": "21/07/2001" + }, + { + "id": 80174, + "category": 0, + "cover": { + "id": 61902, + "height": 468, + "image_id": "ah4luoi90ehyeajwu3pc", + "width": 260 + }, + "first_release_date": "1995-09-14T00:00:00.000Z", + "name": "Mario's Super Picross", + "summary": "More than 10 years before Picross DS, there was Mario's Super Picross for Super Nintendo. This classic 'picture crossword' game, previously unavailable outside of Japan, features hundreds of relaxing yet challenging brainteasers.", + "formattedReleaseDate": "14/09/1995" + } + ] + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/searchgame/list_game_empty_success.json b/app/src/debug/assets/mockjson/searchgame/list_game_empty_success.json new file mode 100644 index 00000000..e94d6fab --- /dev/null +++ b/app/src/debug/assets/mockjson/searchgame/list_game_empty_success.json @@ -0,0 +1,6 @@ +{ + "data": { + "list": [], + "count": 0 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/searchgame/list_game_success.json b/app/src/debug/assets/mockjson/searchgame/list_game_success.json new file mode 100644 index 00000000..521ad9dc --- /dev/null +++ b/app/src/debug/assets/mockjson/searchgame/list_game_success.json @@ -0,0 +1,82 @@ +{ + "data": { + "list": [ + { + "_id": "5c70307b902d9c0023d5d561", + "name": "Jogo 01", + "screenshots": [] + }, + { + "_id": "5c702098902d9c0023d5d55b", + "name": "Jogo yara", + "screenshots": [] + }, + { + "_id": "5c6ef89d6059fd00239fdef4", + "name": "um jogo com um titulo enorme que chega ate o final do layout", + "screenshots": [] + }, + { + "_id": "5c6c6c980b914b002337e7de", + "name": "jogo do teste", + "screenshots": [] + }, + { + "_id": "5c66f3fb9321750023d99982", + "name": "nomedojogomuintograndexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "screenshots": [] + }, + { + "_id": "5c65e161860df20023ec848e", + "name": "jogo test", + "screenshots": [] + }, + { + "_id": "5c65d93b860df20023ec848d", + "name": "jogo jogo", + "screenshots": [] + }, + { + "_id": "5c65d8f2860df20023ec848c", + "name": "game jogo", + "screenshots": [] + }, + { + "_id": "5c65d4b8860df20023ec8488", + "name": "oi yara, jogo do ano", + "screenshots": [] + }, + { + "_id": "5c65d2b8860df20023ec8485", + "name": "o jogo da", + "screenshots": [] + }, + { + "_id": "5c65d298860df20023ec8484", + "name": "o jogo da vida", + "screenshots": [] + }, + { + "_id": "5c65d0c4860df20023ec8483", + "name": "o jogo da vida de maerhb", + "screenshots": [] + }, + { + "_id": "5c65d081860df20023ec8482", + "name": "o jogo da minha vida", + "screenshots": [] + }, + { + "_id": "5c645ab0352d58002358f365", + "name": "Um jogo com o nome gigantesco, para poder testar o limite linhas sugerido!", + "screenshots": [] + }, + { + "_id": "5c61733d2da00d00231f99c5", + "name": "jogo 11", + "screenshots": [] + } + ], + "count": 31 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/searchgame/list_game_success_second.json b/app/src/debug/assets/mockjson/searchgame/list_game_success_second.json new file mode 100644 index 00000000..6ad926b5 --- /dev/null +++ b/app/src/debug/assets/mockjson/searchgame/list_game_success_second.json @@ -0,0 +1,82 @@ +{ + "data": { + "list": [ + { + "_id": "5c70307b902d9c0023d5d561", + "name": "JOGO FIRST", + "screenshots": [] + }, + { + "_id": "5c702098902d9c0023d5d55b", + "name": "Jogo yara", + "screenshots": [] + }, + { + "_id": "5c6ef89d6059fd00239fdef4", + "name": "um jogo com um titulo enorme que chega ate o final do layout", + "screenshots": [] + }, + { + "_id": "5c6c6c980b914b002337e7de", + "name": "jogo do teste", + "screenshots": [] + }, + { + "_id": "5c66f3fb9321750023d99982", + "name": "nomedojogomuintograndexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "screenshots": [] + }, + { + "_id": "5c65e161860df20023ec848e", + "name": "jogo test", + "screenshots": [] + }, + { + "_id": "5c65d93b860df20023ec848d", + "name": "jogo jogo", + "screenshots": [] + }, + { + "_id": "5c65d8f2860df20023ec848c", + "name": "game jogo", + "screenshots": [] + }, + { + "_id": "5c65d4b8860df20023ec8488", + "name": "oi yara, jogo do ano", + "screenshots": [] + }, + { + "_id": "5c65d2b8860df20023ec8485", + "name": "o jogo da", + "screenshots": [] + }, + { + "_id": "5c65d298860df20023ec8484", + "name": "o jogo da vida", + "screenshots": [] + }, + { + "_id": "5c65d0c4860df20023ec8483", + "name": "o jogo da vida de maerhb", + "screenshots": [] + }, + { + "_id": "5c65d081860df20023ec8482", + "name": "o jogo da minha vida", + "screenshots": [] + }, + { + "_id": "5c645ab0352d58002358f365", + "name": "Um jogo com o nome gigantesco, para poder testar o limite linhas sugerido!", + "screenshots": [] + }, + { + "_id": "5c61733d2da00d00231f99c5", + "name": "jogo 11", + "screenshots": [] + } + ], + "count": 31 + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/searchgame/register_game_success.json b/app/src/debug/assets/mockjson/searchgame/register_game_success.json new file mode 100644 index 00000000..572d4447 --- /dev/null +++ b/app/src/debug/assets/mockjson/searchgame/register_game_success.json @@ -0,0 +1,15 @@ +{ + "message": [ + "Jogo salvo" + ], + "data": { + "_id": "5c48ca7ae07db9002375d5a6", + "title": "Fallout 76", + "createdBy": { + "_id": "5c1ab12e7c0f4f002272357e", + "name": "JOAO DAS NEVES" + }, + "createdAt": "2019-01-23T20:11:38.515Z", + "updatedAt": "2019-01-23T20:11:38.515Z" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/token/token_update_success.json b/app/src/debug/assets/mockjson/token/token_update_success.json new file mode 100644 index 00000000..291af523 --- /dev/null +++ b/app/src/debug/assets/mockjson/token/token_update_success.json @@ -0,0 +1,5 @@ +{ + "message": [ + "Token atualizado" + ] +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/user/get_cities_success.json b/app/src/debug/assets/mockjson/user/get_cities_success.json new file mode 100644 index 00000000..e21556cd --- /dev/null +++ b/app/src/debug/assets/mockjson/user/get_cities_success.json @@ -0,0 +1,195 @@ +{ + "message": [ + "Estado encontrado" + ], + "data": { + "cities": [ + "Abreu e Lima", + "Afogados da Ingazeira", + "Afrânio", + "Agrestina", + "Água Preta", + "Águas Belas", + "Alagoinha", + "Aliança", + "Altinho", + "Amaraji", + "Angelim", + "Araçoiaba", + "Araripina", + "Arcoverde", + "Barra de Guabiraba", + "Barreiros", + "Belém de Maria", + "Belém de São Francisco", + "Belo Jardim", + "Betânia", + "Bezerros", + "Bodocó", + "Bom Conselho", + "Bom Jardim", + "Bonito", + "Brejão", + "Brejinho", + "Brejo da Madre de Deus", + "Buenos Aires", + "Buíque", + "Cabo de Santo Agostinho", + "Cabrobó", + "Cachoeirinha", + "Caetés", + "Calçado", + "Calumbi", + "Camaragibe", + "Camocim de São Félix", + "Camutanga", + "Canhotinho", + "Capoeiras", + "Carnaíba", + "Carnaubeira da Penha", + "Carpina", + "Caruaru", + "Casinhas", + "Catende", + "Cedro", + "Chã de Alegria", + "Chã Grande", + "Condado", + "Correntes", + "Cortês", + "Cumaru", + "Cupira", + "Custódia", + "Dormentes", + "Escada", + "Exu", + "Feira Nova", + "Fernando de Noronha", + "Ferreiros", + "Flores", + "Floresta", + "Frei Miguelinho", + "Gameleira", + "Garanhuns", + "Glória do Goitá", + "Goiana", + "Granito", + "Gravatá", + "Iati", + "Ibimirim", + "Ibirajuba", + "Igarassu", + "Iguaraci", + "Inajá", + "Ingazeira", + "Ipojuca", + "Ipubi", + "Itacuruba", + "Itaíba", + "Itamaracá", + "Itambé", + "Itapetim", + "Itapissuma", + "Itaquitinga", + "Jaboatão dos Guararapes", + "Jaqueira", + "Jataúba", + "Jatobá", + "João Alfredo", + "Joaquim Nabuco", + "Jucati", + "Jupi", + "Jurema", + "Lagoa do Carro", + "Lagoa do Itaenga", + "Lagoa do Ouro", + "Lagoa dos Gatos", + "Lagoa Grande", + "Lajedo", + "Limoeiro", + "Macaparana", + "Machados", + "Manari", + "Maraial", + "Mirandiba", + "Moreilândia", + "Moreno", + "Nazaré da Mata", + "Olinda", + "Orobó", + "Orocó", + "Ouricuri", + "Palmares", + "Palmeirina", + "Panelas", + "Paranatama", + "Parnamirim", + "Passira", + "Paudalho", + "Paulista", + "Pedra", + "Pesqueira", + "Petrolândia", + "Petrolina", + "Poção", + "Pombos", + "Primavera", + "Quipapá", + "Quixaba", + "Recife", + "Riacho das Almas", + "Ribeirão", + "Rio Formoso", + "Sairé", + "Salgadinho", + "Salgueiro", + "Saloá", + "Sanharó", + "Santa Cruz", + "Santa Cruz da Baixa Verde", + "Santa Cruz do Capibaribe", + "Santa Filomena", + "Santa Maria da Boa Vista", + "Santa Maria do Cambucá", + "Santa Terezinha", + "São Benedito do Sul", + "São Bento do Una", + "São Caitano", + "São João", + "São Joaquim do Monte", + "São José da Coroa Grande", + "São José do Belmonte", + "São José do Egito", + "São Lourenço da Mata", + "São Vicente Ferrer", + "Serra Talhada", + "Serrita", + "Sertânia", + "Sirinhaém", + "Solidão", + "Surubim", + "Tabira", + "Tacaimbó", + "Tacaratu", + "Tamandaré", + "Taquaritinga do Norte", + "Terezinha", + "Terra Nova", + "Timbaúba", + "Toritama", + "Tracunhaém", + "Trindade", + "Triunfo", + "Tupanatinga", + "Tuparetama", + "Venturosa", + "Verdejante", + "Vertente do Lério", + "Vertentes", + "Vicência", + "Vitória de Santo Antão", + "Xexéu" + ], + "_id": "5a107a691592ca19f7b4a860" + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/user/get_states_success.json b/app/src/debug/assets/mockjson/user/get_states_success.json new file mode 100644 index 00000000..0ee81341 --- /dev/null +++ b/app/src/debug/assets/mockjson/user/get_states_success.json @@ -0,0 +1,16 @@ +{ + "data": { + "list": [ + { + "_id": "1", + "initials": "INITIALS 01", + "name": "NAME 01" + }, + { + "_id": "2", + "initials": "INITALS 02", + "name": "NAME 02" + } + ] + } +} \ No newline at end of file diff --git a/app/src/debug/assets/mockjson/user/register_user_success.json b/app/src/debug/assets/mockjson/user/register_user_success.json new file mode 100644 index 00000000..f6b4442a --- /dev/null +++ b/app/src/debug/assets/mockjson/user/register_user_success.json @@ -0,0 +1,19 @@ +{ + "message": [ + "Usuário salvo" + ], + "data": { + "_id": "123456789", + "name": "ZÉ PEQUENO", + "email": "pequeno.ze@morro.com", + "phone": "66 987699876", + "state": { + "_id": "5a107a691592ca19f7b4a860", + "initials": "PE", + "name": "Pernambuco" + }, + "city": "Recife", + "createdAt": "2019-01-17T21:36:04.584Z", + "updatedAt": "2019-01-17T21:36:04.584Z" + } +} \ No newline at end of file diff --git a/app/src/debug/java/br/com/concrete/tentacle/testing/BottomBarTestActivity.kt b/app/src/debug/java/br/com/concrete/tentacle/testing/BottomBarTestActivity.kt new file mode 100644 index 00000000..7264281b --- /dev/null +++ b/app/src/debug/java/br/com/concrete/tentacle/testing/BottomBarTestActivity.kt @@ -0,0 +1,18 @@ +package br.com.concrete.tentacle.testing + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import br.com.concrete.tentacle.R +import kotlinx.android.synthetic.main.activity_host.* + +class BottomBarTestActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_bottom_bar_test) + + bottomBar.startListener { + // do nothing + } + } +} \ No newline at end of file diff --git a/app/src/debug/java/br/com/concrete/tentacle/testing/GameViewTestActivity.kt b/app/src/debug/java/br/com/concrete/tentacle/testing/GameViewTestActivity.kt new file mode 100644 index 00000000..5bbc3014 --- /dev/null +++ b/app/src/debug/java/br/com/concrete/tentacle/testing/GameViewTestActivity.kt @@ -0,0 +1,13 @@ +package br.com.concrete.tentacle.testing + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import br.com.concrete.tentacle.R + +class GameViewTestActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_game_view_test) + } +} \ No newline at end of file diff --git a/app/src/debug/java/br/com/concrete/tentacle/testing/SingleFragmentTestActivity.kt b/app/src/debug/java/br/com/concrete/tentacle/testing/SingleFragmentTestActivity.kt new file mode 100644 index 00000000..4764b8f0 --- /dev/null +++ b/app/src/debug/java/br/com/concrete/tentacle/testing/SingleFragmentTestActivity.kt @@ -0,0 +1,37 @@ +package br.com.concrete.tentacle.testing + +import android.os.Bundle +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.fragment.app.Fragment +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.base.BaseActivity + +/** +* Used for testing fragments inside a fake activity. +*/ +class SingleFragmentTestActivity : BaseActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val content = FrameLayout(this).apply { + layoutParams = FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + id = R.id.fragment + } + setContentView(content) + } + + fun setFragment(fragment: Fragment) { + supportFragmentManager.beginTransaction() + .add(R.id.fragment, fragment, "TEST") + .commit() + } + + fun replaceFragment(fragment: Fragment) { + supportFragmentManager.beginTransaction() + .replace(R.id.fragment, fragment) + .commit() + } +} \ No newline at end of file diff --git a/app/src/debug/java/br/com/concrete/tentacle/testing/SingleFragmentTestActivityNoActionBarNoBottomBar.kt b/app/src/debug/java/br/com/concrete/tentacle/testing/SingleFragmentTestActivityNoActionBarNoBottomBar.kt new file mode 100644 index 00000000..2bdbbb0a --- /dev/null +++ b/app/src/debug/java/br/com/concrete/tentacle/testing/SingleFragmentTestActivityNoActionBarNoBottomBar.kt @@ -0,0 +1,34 @@ +package br.com.concrete.tentacle.testing + +import android.os.Bundle +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import br.com.concrete.tentacle.R + +class SingleFragmentTestActivityNoActionBarNoBottomBar : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val content = FrameLayout(this).apply { + layoutParams = FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + id = R.id.fragment + } + setContentView(content) + } + + fun setFragment(fragment: Fragment) { + supportFragmentManager.beginTransaction() + .add(R.id.fragment, fragment, "TEST") + .commit() + } + + fun replaceFragment(fragment: Fragment) { + supportFragmentManager.beginTransaction() + .replace(R.id.fragment, fragment) + .commit() + } +} \ No newline at end of file diff --git a/app/src/debug/res/layout/activity_bottom_bar_test.xml b/app/src/debug/res/layout/activity_bottom_bar_test.xml new file mode 100644 index 00000000..1a4a5306 --- /dev/null +++ b/app/src/debug/res/layout/activity_bottom_bar_test.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/debug/res/layout/activity_game_view_test.xml b/app/src/debug/res/layout/activity_game_view_test.xml new file mode 100644 index 00000000..c4d8c444 --- /dev/null +++ b/app/src/debug/res/layout/activity_game_view_test.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/debug/res/mipmap-hdpi/ic_launcher.png b/app/src/debug/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..3ef659b3 Binary files /dev/null and b/app/src/debug/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 00000000..c30efdb8 Binary files /dev/null and b/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/debug/res/mipmap-mdpi/ic_launcher.png b/app/src/debug/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..dadc49d1 Binary files /dev/null and b/app/src/debug/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 00000000..3166ceec Binary files /dev/null and b/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/debug/res/mipmap-xhdpi/ic_launcher.png b/app/src/debug/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..738018f5 Binary files /dev/null and b/app/src/debug/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 00000000..c658dcb9 Binary files /dev/null and b/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png b/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..e5df15bf Binary files /dev/null and b/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..e899c025 Binary files /dev/null and b/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..168ab914 Binary files /dev/null and b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..367ec485 Binary files /dev/null and b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..f85fa7d1 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/dummy_filter_itens_library.json b/app/src/main/assets/dummy_filter_itens_library.json new file mode 100644 index 00000000..3dc52be2 --- /dev/null +++ b/app/src/main/assets/dummy_filter_itens_library.json @@ -0,0 +1,32 @@ +[ + { + "title":"Plataformas", + "icon":"ic_game", + "subItems":[ + { + "queryParameter":"PS3", + "name":"Playstation 3" + }, + { + "queryParameter":"PS4", + "name":"Playstation 4" + }, + { + "queryParameter":"XBOX360", + "name":"XBox 360" + }, + { + "queryParameter":"XBOXONE", + "name":"XBox One" + }, + { + "queryParameter":"NINTENDO3DS", + "name":"Nintendo 3DS" + }, + { + "queryParameter":"NINTENDOSWITCH", + "name":"Nintendo Switch" + } + ] + } +] \ No newline at end of file diff --git a/app/src/main/assets/dummy_fiter_itens_my_games.json b/app/src/main/assets/dummy_fiter_itens_my_games.json new file mode 100644 index 00000000..8aa1d187 --- /dev/null +++ b/app/src/main/assets/dummy_fiter_itens_my_games.json @@ -0,0 +1,12 @@ +[ + { + "title":"Status do jogo", + "icon":"ic_filter_status", + "subItems":[ + { + "queryParameter":"UNAVAILABLE", + "name":"Mostrar jogos indisponíveis" + } + ] + } +] \ No newline at end of file diff --git a/app/src/main/assets/dummy_fiter_itens_my_reservation_show_history.json b/app/src/main/assets/dummy_fiter_itens_my_reservation_show_history.json new file mode 100644 index 00000000..91a72866 --- /dev/null +++ b/app/src/main/assets/dummy_fiter_itens_my_reservation_show_history.json @@ -0,0 +1,12 @@ +[ + { + "title":"Histórico", + "icon":"ic_filter_status", + "subItems":[ + { + "queryParameter":"UNAVAILABLE", + "name":"Mostrar jogos já emprestado" + } + ] + } +] \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/base/AppTentacle.kt b/app/src/main/java/br/com/concrete/tentacle/base/AppTentacle.kt new file mode 100644 index 00000000..2b34d429 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/base/AppTentacle.kt @@ -0,0 +1,71 @@ +package br.com.concrete.tentacle.base + +import android.app.Application +import android.app.NotificationChannel +import android.app.NotificationManager +import android.os.Build +import android.util.Log +import br.com.concrete.tentacle.BuildConfig +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.di.PROPERTY_BASE_URL +import br.com.concrete.tentacle.di.androidModule +import br.com.concrete.tentacle.di.eventsModule +import br.com.concrete.tentacle.di.networkModule +import br.com.concrete.tentacle.di.repositoryModule +import br.com.concrete.tentacle.di.viewModelModule +import br.com.concrete.tentacle.utils.LogWrapper +import com.crashlytics.android.Crashlytics +import com.crashlytics.android.answers.Answers +import com.google.android.gms.tasks.OnCompleteListener +import com.google.firebase.iid.FirebaseInstanceId +import io.fabric.sdk.android.Fabric +import org.koin.android.ext.android.startKoin + +class AppTentacle : Application() { + + companion object { + var TOKEN: String = String() + } + + override fun onCreate() { + super.onCreate() + + Fabric.with(this, Answers(), Crashlytics()) + + startKoin(this, + listOf(androidModule, + networkModule, + viewModelModule, + repositoryModule, + eventsModule), + + extraProperties = mapOf(PROPERTY_BASE_URL to BuildConfig.BASE_URL)) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // Create channel to show notifications. + val channelId = getString(R.string.default_notification_channel_id) + val channelName = getString(R.string.default_notification_channel_name) + val notificationManager = getSystemService(NotificationManager::class.java) + notificationManager?.createNotificationChannel( + NotificationChannel(channelId, + channelName, NotificationManager.IMPORTANCE_LOW) + ) + } + + FirebaseInstanceId.getInstance().instanceId + .addOnCompleteListener(OnCompleteListener { task -> + if (!task.isSuccessful) { + Log.w("TAG", "getInstanceId failed", task.exception) + return@OnCompleteListener + } + // Get new Instance ID token + val token = task.result?.token + TOKEN = token!! + // Log and toast + val msg = getString(R.string.msg_token_fmt, token) + LogWrapper.log("TAG", msg) + }) + + registerActivityLifecycleCallbacks(BaseActivityLifecycleCallback()) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/base/BaseActivity.kt b/app/src/main/java/br/com/concrete/tentacle/base/BaseActivity.kt new file mode 100644 index 00000000..d1a6e7f4 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/base/BaseActivity.kt @@ -0,0 +1,155 @@ +package br.com.concrete.tentacle.base + +import android.content.DialogInterface +import android.content.Intent +import android.content.pm.ActivityInfo +import android.net.Uri +import android.os.Bundle +import android.view.MenuItem +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.data.models.ErrorResponse +import br.com.concrete.tentacle.extensions.ActivityAnimation +import br.com.concrete.tentacle.extensions.logout +import br.com.concrete.tentacle.features.HostActivity +import br.com.concrete.tentacle.utils.DialogUtils +import br.com.concrete.tentacle.utils.SingleEvent +import io.reactivex.functions.Consumer +import java.net.HttpURLConnection +import br.com.concrete.tentacle.utils.HTTP_UPGRADE_REQUIRED + +abstract class BaseActivity : AppCompatActivity(), Consumer> { + + companion object { + const val INVALID_ICON = -1 + const val INVALID_TITLE = -1 + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + + override fun accept(consumer: SingleEvent) { + consumer.getContentIfNotHandler()?.let { + when (it) { + is Int -> { + if (it == HttpURLConnection.HTTP_UNAUTHORIZED) { + DialogUtils.showDialog( + context = this, + title = getString(R.string.something_happened), + message = getString(R.string.session_expired_text), + positiveText = getString(R.string.ok), + contentView = R.layout.custom_dialog_error, + positiveListener = DialogInterface.OnClickListener { _, _ -> + logout() + } + ) + } + } + } + } + } + + fun setupToolbar() { + setupToolbar(INVALID_TITLE, INVALID_ICON, true) + } + + fun setupToolbar(@StringRes title: Int, @DrawableRes icon: Int) { + setupToolbar(title, icon, true) + } + + fun setupToolbar(@DrawableRes icon: Int) { + setupToolbar(INVALID_TITLE, icon, true) + } + + fun setupToolbar(displayHome: Boolean) { + setupToolbar(INVALID_TITLE, INVALID_ICON, displayHome) + } + + fun setSupportActionBarWithIcon(toolbar: Toolbar?, @StringRes title: Int, @DrawableRes icon: Int) { + super.setSupportActionBar(toolbar) + setupToolbar(title, icon) + } + + fun setupToolbar( + title: Int, + icon: Int, + displayHome: Boolean = true + ) { + supportActionBar?.let { actionBar -> + if (title != INVALID_TITLE) { + setToolbarTitle(title) + } + + if (icon != -1 && displayHome) { + actionBar.setHomeAsUpIndicator(icon) + } + actionBar.setDisplayShowHomeEnabled(displayHome) + actionBar.setDisplayHomeAsUpEnabled(displayHome) + } + } + + fun setToolbarTitle(@StringRes title: Int) { + supportActionBar?.let { + it.title = getString(title) + } + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + android.R.id.home -> { + if (this !is HostActivity) { + onBackPressed() + } + return true + } + else -> super.onOptionsItemSelected(item) + } + } + + open fun showError(errors: ErrorResponse?, title: String = "Erro") { + var positiveButton = getString(R.string.ok) + var negativeButton: String? = null + + errors?.let { errorResponse -> + errorResponse.messageInt.map { error -> + errorResponse.message.add(getString(error)) + } + + val ers = errorResponse.toString() + var positive = DialogInterface.OnClickListener { _, _ -> } + + if (errors.statusCode == HTTP_UPGRADE_REQUIRED) { + positiveButton = getString(R.string.update) + negativeButton = getString(R.string.not_delete) + positive = DialogInterface.OnClickListener { _, _ -> + startActivity( + Intent( + Intent.ACTION_VIEW, Uri.parse( + errors.updateUrl + ) + ) + ) + } + } + + DialogUtils.showDialog( + context = this, + title = if (title == "Erro") getString(R.string.something_happened) else title, + message = ers, + positiveText = positiveButton, + positiveListener = positive, + negativeText = negativeButton, + contentView = R.layout.custom_dialog_error + ) + } + } + + open fun getFinishActivityTransition(): ActivityAnimation { + return ActivityAnimation.TRANSLATE_RIGHT + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/base/BaseActivityLifecycleCallback.kt b/app/src/main/java/br/com/concrete/tentacle/base/BaseActivityLifecycleCallback.kt new file mode 100644 index 00000000..14a4420c --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/base/BaseActivityLifecycleCallback.kt @@ -0,0 +1,48 @@ +package br.com.concrete.tentacle.base + +import android.app.Activity +import android.app.Application +import android.os.Bundle +import br.com.concrete.tentacle.data.eventPublisher.EventPublisherContract +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.functions.Consumer +import org.koin.standalone.KoinComponent +import org.koin.standalone.inject + +class BaseActivityLifecycleCallback : Application.ActivityLifecycleCallbacks, KoinComponent { + + private val eventPublisher: EventPublisherContract by inject() + + private val disposables = CompositeDisposable() + + override fun onActivityPaused(activity: Activity?) { + activity?.let { + if (it is BaseActivity) { + disposables.clear() + } + } + } + + override fun onActivityResumed(activity: Activity?) { + activity?.let { + if (it is BaseActivity) { + disposables.add(eventPublisher.subscribe(it as Consumer)) + } + } + } + + override fun onActivityStarted(activity: Activity?) { + } + + override fun onActivityDestroyed(activity: Activity?) { + } + + override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) { + } + + override fun onActivityStopped(activity: Activity?) { + } + + override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) { + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/base/BaseAdapter.kt b/app/src/main/java/br/com/concrete/tentacle/base/BaseAdapter.kt new file mode 100644 index 00000000..d81d7022 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/base/BaseAdapter.kt @@ -0,0 +1,49 @@ +package br.com.concrete.tentacle.base + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import br.com.concrete.tentacle.R + +class BaseAdapter( + var elements: ArrayList = ArrayList(), + val layout: Int, + private val holder: (mL: View) -> RecyclerView.ViewHolder, + val holderCallback: (holder: RecyclerView.ViewHolder, T) -> Unit +) : RecyclerView.Adapter() { + + private val VIEW_TYPE_ITEM = 0 + private val VIEW_TYPE_LOADING = 1 + + override fun getItemCount() = if (elements.isNullOrEmpty()) VIEW_TYPE_LOADING else elements.size + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder) { + is ProgressBarViewHolder -> holder + else -> elements[position]?.let { holderCallback(holder, it) } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + val inflater = LayoutInflater.from(parent.context) + return if (viewType == VIEW_TYPE_LOADING) { + ProgressBarViewHolder( + inflater + .inflate(R.layout.item_progress, parent, false) + ) + } else { + holder( + inflater + .inflate(layout, parent, false) + ) + } + } + + fun setNewList(elements: ArrayList) { + this.elements = elements + notifyDataSetChanged() + } + + override fun getItemViewType(position: Int) = if (elements[position] == null) VIEW_TYPE_LOADING else VIEW_TYPE_ITEM +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/base/BaseFragment.kt b/app/src/main/java/br/com/concrete/tentacle/base/BaseFragment.kt new file mode 100644 index 00000000..26967e47 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/base/BaseFragment.kt @@ -0,0 +1,83 @@ +package br.com.concrete.tentacle.base + +import android.content.Context +import android.content.DialogInterface +import android.content.Intent +import android.net.Uri +import androidx.fragment.app.Fragment +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.data.interfaces.CallBack +import br.com.concrete.tentacle.data.models.ErrorResponse +import br.com.concrete.tentacle.extensions.callSnackbar +import br.com.concrete.tentacle.utils.DialogUtils +import br.com.concrete.tentacle.utils.HTTP_UPGRADE_REQUIRED +import io.reactivex.functions.Consumer +import org.jetbrains.annotations.TestOnly + +abstract class BaseFragment : Fragment() { + + protected var callback: CallBack? = null + + override fun onAttach(context: Context) { + super.onAttach(context) + if (context is CallBack) callback = context + } + + private fun getEventObserver() = Consumer { + } + + protected fun showError(errors: ErrorResponse?, title: String = "Erro") { + activity?.let { + if (it is BaseActivity) { + it.showError(errors, title) + return + } + } + + var positiveButton = getString(R.string.ok) + var negativeButton: String? = null + + if (errors != null) { + context?.let { ctx -> + errors.messageInt.map { error -> + errors.message.add(ctx.getString(error)) + } + } + val ers = errors.toString() + var positive = DialogInterface.OnClickListener { _, _ -> } + + if (errors.statusCode == HTTP_UPGRADE_REQUIRED) { + positiveButton = getString(R.string.update) + negativeButton = getString(R.string.not_delete) + positive = DialogInterface.OnClickListener { _, _ -> + startActivity( + Intent( + Intent.ACTION_VIEW, Uri.parse( + errors.updateUrl + ) + ) + ) + } + } + + activity?.let { + DialogUtils.showDialog( + context = it, + title = if (title == "Erro") getString(R.string.something_happened) else title, + message = ers, + positiveText = positiveButton, + positiveListener = positive, + negativeText = negativeButton, + contentView = R.layout.custom_dialog_error + ) + } + } + } + + abstract fun getToolbarTitle(): Int + + @TestOnly + protected fun showMessageForTest(resMsg: Int) { + context?.callSnackbar(view!!, getString(resMsg)) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/base/BaseSearchFragment.kt b/app/src/main/java/br/com/concrete/tentacle/base/BaseSearchFragment.kt new file mode 100644 index 00000000..d435824b --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/base/BaseSearchFragment.kt @@ -0,0 +1,113 @@ +package br.com.concrete.tentacle.base + +import android.annotation.SuppressLint +import android.os.Bundle +import android.text.InputType +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.widget.EditText +import android.widget.ImageView +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.SearchView +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.callSnackbar +import io.reactivex.Observable +import io.reactivex.ObservableOnSubscribe +import java.util.concurrent.TimeUnit + +const val TIME_OUT: Long = 550 +const val MINIMAL_CHARACTER: Int = 2 + +@SuppressLint("CheckResult") +abstract class BaseSearchFragment : BaseFragment(), + MenuItem.OnActionExpandListener { + + private lateinit var searchView: SearchView + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setHasOptionsMenu(true) + initView() + initViewModel() + initListener() + initRecyclerView() + setupToolbar() + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + setupSearchView(menu, inflater) + + super.onCreateOptionsMenu(menu, inflater) + } + + private fun setupSearchView(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.menu_search, menu) + val menuItem: MenuItem = menu.findItem(R.id.action_search) + when (menuItem.actionView) { + is SearchView -> initSearchView(menuItem) + } + } + + private fun initSearchView(menuItem: MenuItem) { + searchView = menuItem.actionView as SearchView + context?.let { + searchView.queryHint = it.getString(R.string.search) + } + + searchView.isIconified = false + searchView.setIconifiedByDefault(true) + + val closeButton = searchView.findViewById(R.id.search_close_btn) + val editText = searchView.findViewById(R.id.search_src_text) + editText.inputType = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES + + closeButton.setOnClickListener { + editText.setText("") + searchView.setIconifiedByDefault(true) + } + + Observable.create(ObservableOnSubscribe { subscriber -> + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextChange(newText: String?): Boolean { + subscriber.onNext(newText!!) + return false + } + + override fun onQueryTextSubmit(query: String?): Boolean { + subscriber.onNext(query!!) + return false + } + }) + }) + .map { text -> text.toLowerCase().trim() } + .debounce(TIME_OUT, TimeUnit.MILLISECONDS) + .filter { text -> validateSearch(text) } + .subscribe { text -> getSearchGame(text) } + } + + fun validateSearch(search: String) = search.trim().length >= MINIMAL_CHARACTER + + private fun setupToolbar() { + (activity as? AppCompatActivity)?.supportActionBar?.title = titleToolbar() + } + + fun getQuerySearchView() = searchView.query.toString() + + fun callSnackBar(message: String) { + context?.let { context -> + view?.let { + context.callSnackbar(it, message) + } + } + } + + abstract fun titleToolbar(): String + abstract fun initView() + abstract fun initListener() + abstract fun initViewModel() + abstract fun initRecyclerView() + abstract fun getSearchGame(searchGame: String) + abstract fun clearListGame() +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/base/BaseViewModel.kt b/app/src/main/java/br/com/concrete/tentacle/base/BaseViewModel.kt new file mode 100644 index 00000000..9fc0bf1b --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/base/BaseViewModel.kt @@ -0,0 +1,74 @@ +package br.com.concrete.tentacle.base + +import androidx.lifecycle.LifecycleObserver +import androidx.lifecycle.ViewModel +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.data.eventPublisher.EventPublisherContract +import br.com.concrete.tentacle.data.models.ErrorResponse +import br.com.concrete.tentacle.utils.DEFAULT_EXCEPTION_STATUS_CODE +import br.com.concrete.tentacle.utils.HTTP_UPGRADE_REQUIRED +import br.com.concrete.tentacle.utils.LogWrapper +import com.google.gson.GsonBuilder +import io.reactivex.disposables.CompositeDisposable +import org.koin.standalone.KoinComponent +import org.koin.standalone.inject +import retrofit2.HttpException +import java.io.IOException +import java.net.HttpURLConnection + +open class BaseViewModel : ViewModel(), LifecycleObserver, KoinComponent { + + private val eventPublisher: EventPublisherContract by inject() + + protected val disposables = CompositeDisposable() + + protected fun notKnownError(error: Throwable): ErrorResponse? { + + val gson = GsonBuilder().create() + var errorResponse: ErrorResponse? = null + val msgsInt = ArrayList() + + when (error) { + is HttpException -> { + when (error.code()) { + HttpURLConnection.HTTP_BAD_REQUEST -> { + errorResponse = gson.fromJson( + error.response().errorBody()?.charStream(), + ErrorResponse::class.java + ) + } + HttpURLConnection.HTTP_UNAUTHORIZED -> { + eventPublisher.publish(HttpURLConnection.HTTP_UNAUTHORIZED) + } + HttpURLConnection.HTTP_NOT_FOUND -> errorResponse = gson.fromJson( + error.response().errorBody()?.charStream(), + ErrorResponse::class.java + ) + HTTP_UPGRADE_REQUIRED -> errorResponse = gson.fromJson( + error.response().errorBody()?.charStream(), + ErrorResponse::class.java + ) + else -> { + msgsInt.add(R.string.unknow_error) + errorResponse = ErrorResponse(messageInt = msgsInt) + } + } + errorResponse?.statusCode = error.code() + } + is IOException -> { + msgsInt.add(R.string.no_internet_connection) + errorResponse = ErrorResponse( + statusCode = DEFAULT_EXCEPTION_STATUS_CODE, + messageInt = msgsInt) + LogWrapper.log("ERROR TAG: ", "No Internet Connection.") + } + } + + return errorResponse + } + + override fun onCleared() { + disposables.dispose() + super.onCleared() + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/base/ProgressBarViewHolder.kt b/app/src/main/java/br/com/concrete/tentacle/base/ProgressBarViewHolder.kt new file mode 100644 index 00000000..6cb6da9f --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/base/ProgressBarViewHolder.kt @@ -0,0 +1,6 @@ +package br.com.concrete.tentacle.base + +import android.view.View +import androidx.recyclerview.widget.RecyclerView + +class ProgressBarViewHolder(val item: View) : RecyclerView.ViewHolder(item) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/BaseTentacleLabeledWidget.kt b/app/src/main/java/br/com/concrete/tentacle/custom/BaseTentacleLabeledWidget.kt new file mode 100644 index 00000000..a87080eb --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/BaseTentacleLabeledWidget.kt @@ -0,0 +1,21 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.LinearLayout +import kotlinx.android.synthetic.main.tentacle_edit_text_layout.view.* + +abstract class BaseTentacleLabeledWidget( + context: Context, + attrs: AttributeSet +) : LinearLayout(context, attrs) { + + fun showError(show: Boolean) { + tvError.visibility = if (show) View.VISIBLE else View.INVISIBLE + } + + fun setError(errorMsg: String) { + tvError.text = errorMsg + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/BottomBar.kt b/app/src/main/java/br/com/concrete/tentacle/custom/BottomBar.kt new file mode 100644 index 00000000..742b4d50 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/BottomBar.kt @@ -0,0 +1,61 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.LinearLayout +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.asSequence +import br.com.concrete.tentacle.extensions.withStyledAttributes +import br.com.concrete.tentacle.utils.DEFAULT_INVALID_RESOURCE +import kotlinx.android.synthetic.main.bottom_bar.view.* + +class BottomBar( + context: Context, + attrs: AttributeSet +) : LinearLayout(context, attrs) { + + private var iconBottomBarSelected = R.id.action_home + + init { + View.inflate(context, R.layout.bottom_bar, this) + + context.withStyledAttributes( + attrs, + R.styleable.BottomBar, + 0, + 0 + ) { + val defaultSelectedPosition = getInt(R.styleable.BottomBar_defaultSelectedPosition, DEFAULT_INVALID_RESOURCE) + if (defaultSelectedPosition != DEFAULT_INVALID_RESOURCE) { + updateBottomBarByPosition(defaultSelectedPosition) + } + } + } + + fun startListener(listener: (Int) -> Unit) { + container.asSequence().toList().map { item -> + item.setOnClickListener { + if (item.id != iconBottomBarSelected) { + updateBottomBar(item.id) + listener(item.id) + } + iconBottomBarSelected = item.id + } + } + } + + fun updateBottomBar(id: Int) { + container.asSequence().toList().map { item -> + if (item is IconBottomBar) { + item.setViewSelected(id == item.id) + iconBottomBarSelected = item.id + } + } + } + + private fun updateBottomBarByPosition(position: Int) { + val item = container.asSequence().toList()[position] + if (item is IconBottomBar) item.setViewSelected(true) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/ButtonView.kt b/app/src/main/java/br/com/concrete/tentacle/custom/ButtonView.kt new file mode 100644 index 00000000..924a920e --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/ButtonView.kt @@ -0,0 +1,74 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.graphics.Color +import android.util.AttributeSet +import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.getFloatFromRes +import br.com.concrete.tentacle.extensions.withStyledAttributes +import kotlinx.android.synthetic.main.button_custom.view.* + +open class ButtonView( + context: Context, + attrs: AttributeSet +) : ConstraintLayout(context, attrs) { + + init { + View.inflate(context, R.layout.button_custom, this) + var buttonName: String? + var textColor: String? + var textSize: Float + + context.withStyledAttributes( + attrs, + R.styleable.ButtonView, + 0, + 0 + ) { + buttonName = getString(R.styleable.ButtonView_buttonName) + textColor = getString(R.styleable.ButtonView_textColorButton) + textSize = getFloat(R.styleable.ButtonView_textSizeButton, context.getFloatFromRes(R.dimen.defaultTextSize)) + + labelCustomView(buttonName, textColor, textSize) + } + } + + private fun labelCustomView( + buttonName: String?, + textColor: String?, + textSize: Float + ) { + buttonName?.let { + button.text = if (it.isNotEmpty()) it else context.getString(R.string.button) + } + + button.textSize = textSize + + textColor?.let { + val color: Int = if (it.isNotEmpty()) Color.parseColor(it) else Color.GRAY + button.setTextColor(color) + } + } + + fun isLoading(isLoading: Boolean) { + visibilityProgress(isLoading) + } + + private fun visibilityProgress(condition: Boolean) { + if (condition) { + progressBar.visibility = View.VISIBLE + button.visibility = View.GONE + frameLayout.isEnabled = !condition + } else { + progressBar.visibility = View.GONE + button.visibility = View.VISIBLE + frameLayout.isEnabled = !condition + } + } + + fun setButtonName(btName: String?) { + btName?.let { button.text = btName } + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/ChipCustom.kt b/app/src/main/java/br/com/concrete/tentacle/custom/ChipCustom.kt new file mode 100644 index 00000000..13ac3c4b --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/ChipCustom.kt @@ -0,0 +1,24 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import androidx.core.content.ContextCompat +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.utils.Utils +import com.google.android.material.chip.Chip + +class ChipCustom(context: Context, attrs: AttributeSet?) : Chip(context, attrs) { + + init { + chipBackgroundColor = ContextCompat.getColorStateList(context, R.color.color_chip_state) + chipStrokeColor = null + isCheckedIconVisible = false + isCheckable = true + rippleColor = null + setTextColor(ContextCompat.getColor(context, R.color.textColor)) + textAlignment = View.TEXT_ALIGNMENT_CENTER + chipStrokeWidth = 0f + chipCornerRadius = Utils.dpToPx(20).toFloat() + } +} diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/GameView.kt b/app/src/main/java/br/com/concrete/tentacle/custom/GameView.kt new file mode 100644 index 00000000..51c7a713 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/GameView.kt @@ -0,0 +1,86 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.data.models.Game +import br.com.concrete.tentacle.extensions.getPartOfDate +import br.com.concrete.tentacle.extensions.loadImageUrl +import br.com.concrete.tentacle.extensions.progress +import br.com.concrete.tentacle.extensions.toDate +import br.com.concrete.tentacle.extensions.visible +import br.com.concrete.tentacle.utils.IMAGE_SIZE_TYPE_COVER_SMALL +import br.com.concrete.tentacle.utils.Utils +import kotlinx.android.synthetic.main.game_view_header_layout.view.ivGameCover +import kotlinx.android.synthetic.main.game_view_header_layout.view.rbGame +import kotlinx.android.synthetic.main.game_view_header_layout.view.tvGameName +import kotlinx.android.synthetic.main.game_view_header_layout.view.tvGameReleaseYear +import kotlinx.android.synthetic.main.game_view_header_layout.view.groupStatus +import kotlinx.android.synthetic.main.game_view_layout.view.* +import java.util.Calendar + +class GameView( + context: Context, + attrs: AttributeSet +) : ConstraintLayout(context, attrs) { + init { + View.inflate(context, R.layout.game_view_layout, this) + } + + fun setGame(game: Game) { + + with(game) { + + cover?.imageId?.let { + ivGameCover.loadImageUrl(Utils.assembleGameImageUrl(IMAGE_SIZE_TYPE_COVER_SMALL, it)) + } + + val inflater = LayoutInflater.from(this@GameView.context) + + tvGameName.text = name + rating?.let { + rbGame.progress(it) + } + releaseDate?.let { + tvGameReleaseYear.text = it.toDate().getPartOfDate(Calendar.YEAR) + } + + summary?.let { + tvGameSummary.text = it + } + + gameModes?.let { + gameModeContainer.removeAllViews() + it.forEach { gameMode -> + val tv = inflater.inflate(R.layout.game_mode_text_layout, null) as TextView + gameMode.name?.let { name -> + tv.text = name + gameMode.getIconResource()?.let { icon -> + tv.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0) + } + gameModeContainer.addView(tv) + } + } + } + + genres?.let { + genresContainer.removeAllViews() + it.forEach { genre -> + val tv = inflater.inflate(R.layout.genre_chip_layout, null) as TextView + genre.name?.let { name -> + tv.text = name + genresContainer.addView(tv) + } + } + } + } + } + + fun showStatusView(show: Boolean) { + groupStatus.visible(show) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/IconBottomBar.kt b/app/src/main/java/br/com/concrete/tentacle/custom/IconBottomBar.kt new file mode 100644 index 00000000..9f1cfacc --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/IconBottomBar.kt @@ -0,0 +1,52 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.widget.FrameLayout +import androidx.core.content.ContextCompat +import androidx.core.widget.ImageViewCompat +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.withStyledAttributes +import kotlinx.android.synthetic.main.icon_bottom_bar.view.* + +class IconBottomBar( + context: Context, + attrs: AttributeSet +) : FrameLayout(context, attrs) { + + private var isViewSelected = false + + init { + View.inflate(context, R.layout.icon_bottom_bar, this) + + context.withStyledAttributes( + attrs, + R.styleable.IconBottomBar, + 0, + 0 + ) { + val icon = getDrawable(R.styleable.IconBottomBar_iconBottomBar) + val selected = getBoolean(R.styleable.IconBottomBar_selected, false) + + setup(icon, selected) + } + } + + private fun setup(icon: Drawable?, selected: Boolean) { + icon?.let { + ivIcon.setImageDrawable(it) + } + setViewSelected(selected) + } + + fun setViewSelected(selected: Boolean) { + selectedView.visibility = if (selected) View.VISIBLE else View.INVISIBLE + val colorStateList = ColorStateList.valueOf(ContextCompat.getColor(context, if (selected) R.color.activateIcon else R.color.deactivateIcon)) + ImageViewCompat.setImageTintList(ivIcon, colorStateList) + + isViewSelected = selected + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/ListCustom.kt b/app/src/main/java/br/com/concrete/tentacle/custom/ListCustom.kt new file mode 100644 index 00000000..9ccf4d67 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/ListCustom.kt @@ -0,0 +1,197 @@ +package br.com.concrete.tentacle.custom + +import android.app.Activity +import android.content.Context +import android.util.AttributeSet +import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.hideKeyboard +import br.com.concrete.tentacle.extensions.withStyledAttributes +import br.com.concrete.tentacle.utils.DEFAULT_INVALID_RESOURCE +import br.com.concrete.tentacle.utils.DEFAULT_INVALID_RESOURCE_BOOLEAN +import kotlinx.android.synthetic.main.list_custom.view.buttonAction +import kotlinx.android.synthetic.main.list_custom.view.recyclerListError +import kotlinx.android.synthetic.main.list_custom.view.recyclerListView +import kotlinx.android.synthetic.main.list_error_custom.view.buttonNameError +import kotlinx.android.synthetic.main.progress_include.view.progressBarList + +class ListCustom( + context: Context, + attrs: AttributeSet +) : ConstraintLayout(context, attrs) { + + private var iconReference: Int = DEFAULT_INVALID_RESOURCE + private var errorDescriptionReference: Int = DEFAULT_INVALID_RESOURCE + private var buttonNameErrorReference: Int = DEFAULT_INVALID_RESOURCE + private var buttonNameActionReference: Int = DEFAULT_INVALID_RESOURCE + private var endLessScroll: Boolean = DEFAULT_INVALID_RESOURCE_BOOLEAN + + private var pastVisibleItems: Int = 0 + private var visibleItemCount: Int = 0 + private var totalItemCount: Int = 0 + + private lateinit var mOnScrollListener: OnScrollListener + private var emptyListMessageReference: Int = DEFAULT_INVALID_RESOURCE + + init { + View.inflate(context, R.layout.list_custom, this) + + context.withStyledAttributes( + attrs, + R.styleable.ListCustom, + 0, + 0 + ) { + setLoading(true) + iconReference = getResourceId(R.styleable.ListCustom_icon, DEFAULT_INVALID_RESOURCE) + errorDescriptionReference = getResourceId(R.styleable.ListCustom_errorDescription, DEFAULT_INVALID_RESOURCE) + buttonNameErrorReference = getResourceId(R.styleable.ListCustom_buttonNameError, DEFAULT_INVALID_RESOURCE) + buttonNameActionReference = getResourceId(R.styleable.ListCustom_buttonNameAction, DEFAULT_INVALID_RESOURCE) + emptyListMessageReference = getResourceId(R.styleable.ListCustom_emptyListMessage, DEFAULT_INVALID_RESOURCE) + endLessScroll = getBoolean(R.styleable.ListCustom_endLessScroll, DEFAULT_INVALID_RESOURCE_BOOLEAN) + } + } + + fun updateUi(elements: ArrayList?, filtering: Boolean = false) { + if (elements == null) { + recyclerListError.setUpComponents(iconReference, errorDescriptionReference, buttonNameErrorReference) + showViewError() + } else { + if (elements.isEmpty()) { + val msg = if (filtering) emptyListMessageReference else errorDescriptionReference + recyclerListError.setUpComponents(iconReference, msg, buttonNameErrorReference) + showViewError() + } else { + showViewSuccess() + } + } + } + + private fun showViewSuccess() { + recyclerListView.visibility = View.VISIBLE + recyclerListError.visibility = View.GONE + + if (buttonNameActionReference > DEFAULT_INVALID_RESOURCE) { + buttonAction.setButtonName(context.getString(buttonNameActionReference)) + buttonAction.visibility = View.VISIBLE + setButtonEffect() + } + initEndLessRecyclerView() + } + + private fun setButtonEffect() { + recyclerListView.adapter?.let { + recyclerListView.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + val layoutManager = recyclerListView.layoutManager + if (layoutManager is LinearLayoutManager) { + if (layoutManager.findLastCompletelyVisibleItemPosition() < it.itemCount - 1) { + when (newState) { + View.SCROLL_INDICATOR_BOTTOM -> { + buttonAction.visibility = View.GONE + } + View.SCROLL_INDICATOR_TOP -> { + buttonAction.visibility = View.GONE + } + View.SCROLL_AXIS_NONE -> { + buttonAction.visibility = View.VISIBLE + } + } + } else if (layoutManager.findLastCompletelyVisibleItemPosition() == mOnScrollListener.count()) { + buttonAction.visibility = View.VISIBLE + } + } + super.onScrollStateChanged(recyclerView, newState) + } + }) + } + } + + private fun initEndLessRecyclerView() { + recyclerListView.adapter?.let { + recyclerListView.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + + if (endLessScroll) { + val layoutManager = recyclerView.layoutManager + if (layoutManager is LinearLayoutManager) { + visibleItemCount = layoutManager.childCount + totalItemCount = layoutManager.itemCount + pastVisibleItems = layoutManager.findFirstCompletelyVisibleItemPosition() + } + + if (mOnScrollListener.loadPage() && (visibleItemCount + pastVisibleItems) >= totalItemCount) { + if (mOnScrollListener.count() > mOnScrollListener.sizeElements()) { + mOnScrollListener.loadMore() + buttonAction.visibility = View.GONE + } + } + } + } + }) + } + } + + private fun showViewError() { + recyclerListView.visibility = View.GONE + buttonAction.visibility = View.GONE + recyclerListError.visibility = View.VISIBLE + hideSoftKeyboard() + } + + private fun hideSoftKeyboard() { + context?.let { + if (it is Activity) { + it.hideKeyboard() + } + } + } + + private fun showLoading() { + recyclerListError.visibility = View.GONE + recyclerListView.visibility = View.GONE + progressBarList.visibility = View.VISIBLE + } + + fun setLoading(condition: Boolean) { + progressBarList.visibility = if (condition) View.VISIBLE else View.GONE + } + + fun visibleCustomError(visible: Boolean) { + recyclerListError.visibility = if (visible) View.VISIBLE else View.GONE + } + + fun setErrorMessage(errorCode: Int) { + errorDescriptionReference = errorCode + } + + fun setButtonNameAction(action: Int) { + buttonNameActionReference = action + } + + fun setButtonTextError(errorCode: Int) { + buttonNameErrorReference = errorCode + } + + fun setActionError(action: () -> Unit) { + recyclerListError.buttonNameError.setOnClickListener { + showLoading() + action() + } + } + + fun setOnScrollListener(onScrollListener: OnScrollListener) { + this.mOnScrollListener = onScrollListener + } + + interface OnScrollListener { + fun count(): Int + fun sizeElements(): Int + fun loadMore() + fun loadPage(): Boolean + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/ListError.kt b/app/src/main/java/br/com/concrete/tentacle/custom/ListError.kt new file mode 100644 index 00000000..d6734efa --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/ListError.kt @@ -0,0 +1,48 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.withStyledAttributes +import br.com.concrete.tentacle.utils.DEFAULT_INVALID_RESOURCE +import kotlinx.android.synthetic.main.list_error_custom.view.buttonNameError +import kotlinx.android.synthetic.main.list_error_custom.view.errorDescription +import kotlinx.android.synthetic.main.list_error_custom.view.icon + +class ListError( + context: Context, + attrs: AttributeSet +) : ConstraintLayout(context, attrs) { + + private var iconReferenceError: Int = DEFAULT_INVALID_RESOURCE + private var errorDescriptionTextReference: Int = DEFAULT_INVALID_RESOURCE + private var buttonNameTextErrorReference: Int = DEFAULT_INVALID_RESOURCE + + init { + View.inflate(context, R.layout.list_error_custom, this) + context.withStyledAttributes( + attrs, + R.styleable.ListError, + 0, + 0 + ) { + iconReferenceError = getResourceId(R.styleable.ListError_iconError, DEFAULT_INVALID_RESOURCE) + errorDescriptionTextReference = getResourceId(R.styleable.ListError_errorTextDescription, DEFAULT_INVALID_RESOURCE) + buttonNameTextErrorReference = getResourceId(R.styleable.ListError_buttonNameTextError, DEFAULT_INVALID_RESOURCE) + + setUpComponents(iconReferenceError, errorDescriptionTextReference, buttonNameTextErrorReference) + } + } + + fun setUpComponents(iconReference: Int, errorDescriptionReference: Int, buttonNameReference: Int) { + if (iconReference > DEFAULT_INVALID_RESOURCE) icon.setImageResource(iconReference) + if (errorDescriptionReference > DEFAULT_INVALID_RESOURCE) errorDescription.text = context.getString(errorDescriptionReference) + if (buttonNameReference > DEFAULT_INVALID_RESOURCE) buttonNameError.setButtonName(context.getString(buttonNameReference)) + } + + fun setUpActionErrorButton(error: () -> Unit) { + buttonNameError.setOnClickListener { error() } + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/NoSwipeViewPager.kt b/app/src/main/java/br/com/concrete/tentacle/custom/NoSwipeViewPager.kt new file mode 100644 index 00000000..2843396c --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/NoSwipeViewPager.kt @@ -0,0 +1,43 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.animation.Interpolator +import androidx.viewpager.widget.ViewPager +import java.lang.reflect.Field + +class NoSwipeViewPager(context: Context, attributeSet: AttributeSet) : ViewPager(context, attributeSet) { + + private var mScroller: ScrollerCustomDuration? = null + + init { + try { + val scroller = ViewPager::class.java.getDeclaredField("mScroller") + scroller.isAccessible = true + val interpolator: Field = ViewPager::class.java.getDeclaredField("sInterpolator") + interpolator.isAccessible = true + + mScroller = ScrollerCustomDuration(context, interpolator.get(null) as Interpolator) + scroller.set(this, mScroller) + } catch (ex: Exception) { + ex.printStackTrace() + } + } + + fun setScrollDurationFactor(scrollFactor: Double) { + mScroller?.setScrollDurationFactor(scrollFactor) + } + + override fun onTouchEvent(ev: MotionEvent?): Boolean { + return false + } + + override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { + return false + } + + fun nextPage() { + currentItem += 1 + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/ScrollerCustomDuration.kt b/app/src/main/java/br/com/concrete/tentacle/custom/ScrollerCustomDuration.kt new file mode 100644 index 00000000..9dfc4694 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/ScrollerCustomDuration.kt @@ -0,0 +1,21 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.view.animation.Interpolator +import android.widget.Scroller + +class ScrollerCustomDuration( + context: Context, + interpolator: Interpolator? +) : Scroller(context, interpolator) { + + private var mScrollFactor: Double = 1.0 + + fun setScrollDurationFactor(scrollFactor: Double) { + mScrollFactor = scrollFactor + } + + override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int, duration: Int) { + super.startScroll(startX, startY, dx, dy, (duration * mScrollFactor).toInt()) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/StateButtonView.kt b/app/src/main/java/br/com/concrete/tentacle/custom/StateButtonView.kt new file mode 100644 index 00000000..fe5a6834 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/StateButtonView.kt @@ -0,0 +1,35 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.util.AttributeSet +import androidx.annotation.ColorRes +import androidx.annotation.DrawableRes +import androidx.core.content.ContextCompat +import br.com.concrete.tentacle.R +import kotlinx.android.synthetic.main.button_custom.view.button + +open class StateButtonView( + context: Context, + attrs: AttributeSet +) : ButtonView(context, attrs) { + + open fun enable() { + isEnabled = true + backgroundColor(R.drawable.shape_border_rounded_blue) + textColor(R.color.textColor) + } + + open fun disable() { + isEnabled = false + backgroundColor(R.drawable.shape_border_rounded_diasabled) + textColor(R.color.disableTextButton) + } + + protected fun backgroundColor(@DrawableRes drawable: Int) { + background = ContextCompat.getDrawable(context, drawable) + } + + protected fun textColor(@ColorRes color: Int) { + button.setTextColor(ContextCompat.getColor(context, color)) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/StateButtonWhiteView.kt b/app/src/main/java/br/com/concrete/tentacle/custom/StateButtonWhiteView.kt new file mode 100644 index 00000000..a7269017 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/StateButtonWhiteView.kt @@ -0,0 +1,17 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.util.AttributeSet +import br.com.concrete.tentacle.R + +class StateButtonWhiteView( + context: Context, + attrs: AttributeSet +) : StateButtonView(context, attrs) { + + override fun enable() { + isEnabled = true + backgroundColor(R.drawable.shape_border_rounded_white) + textColor(R.color.colorAccent) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/TentacleEditText.kt b/app/src/main/java/br/com/concrete/tentacle/custom/TentacleEditText.kt new file mode 100644 index 00000000..3dd86a58 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/TentacleEditText.kt @@ -0,0 +1,53 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.text.InputFilter +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.inputmethod.EditorInfo +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.withStyledAttributes +import br.com.concrete.tentacle.utils.DEFAULT_INVALID_RESOURCE +import kotlinx.android.synthetic.main.tentacle_edit_text_layout.view.* + +class TentacleEditText( + context: Context, + attrs: AttributeSet +) : BaseTentacleLabeledWidget(context, attrs) { + + init { + LayoutInflater.from(context).inflate(R.layout.tentacle_edit_text_layout, this, true) + + context.withStyledAttributes( + attrs, + R.styleable.TentacleLabeledWidget, + 0, + 0) { + + val labelText = getResourceId(R.styleable.TentacleLabeledWidget_label, DEFAULT_INVALID_RESOURCE) + val errorText = getResourceId(R.styleable.TentacleLabeledWidget_errorLabel, DEFAULT_INVALID_RESOURCE) + val inputType = getInt(R.styleable.TentacleLabeledWidget_android_inputType, EditorInfo.TYPE_TEXT_VARIATION_NORMAL) + val imeOptions = getInt(R.styleable.TentacleLabeledWidget_android_imeOptions, 0) + val gravity = getInt(R.styleable.TentacleLabeledWidget_android_gravity, 0) + val maxLenght = getInt(R.styleable.TentacleLabeledWidget_android_maxLength, -1) + + if (labelText > DEFAULT_INVALID_RESOURCE) tvLabel.text = context.getString(labelText) + if (errorText > DEFAULT_INVALID_RESOURCE) tvError.text = context.getString(errorText) + + edt.inputType = inputType + edt.imeOptions = imeOptions + edt.gravity = gravity + if (maxLenght >= 0) edt.filters = arrayOf(InputFilter.LengthFilter(maxLenght)) + } + } + + fun getText() = edt.text.toString() + + fun setText(text: String) { + edt.setText(text) + } + + fun setLetterSpacing(space: Float) { + edt.letterSpacing = space + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/custom/TentacleSearchSpinner.kt b/app/src/main/java/br/com/concrete/tentacle/custom/TentacleSearchSpinner.kt new file mode 100644 index 00000000..9fd4e60e --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/custom/TentacleSearchSpinner.kt @@ -0,0 +1,42 @@ +package br.com.concrete.tentacle.custom + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.extensions.withStyledAttributes +import br.com.concrete.tentacle.utils.DEFAULT_INVALID_RESOURCE +import kotlinx.android.synthetic.main.tentacle_search_spinner_layout.view.* + +class TentacleSearchSpinner(context: Context, attrs: AttributeSet) : BaseTentacleLabeledWidget(context, attrs) { + + init { + LayoutInflater.from(context).inflate(R.layout.tentacle_search_spinner_layout, this, true) + + context.withStyledAttributes( + attrs, + R.styleable.TentacleLabeledWidget, + 0, + 0) { + val labelText = getResourceId(R.styleable.TentacleLabeledWidget_label, DEFAULT_INVALID_RESOURCE) + val errorText = getResourceId(R.styleable.TentacleLabeledWidget_errorLabel, DEFAULT_INVALID_RESOURCE) + + if (labelText > DEFAULT_INVALID_RESOURCE) tvLabel.text = context.getString(labelText) + if (errorText > DEFAULT_INVALID_RESOURCE) tvError.text = context.getString(errorText) + } + + showError(false) + } + + fun setText(text: String) { + button.text = text + } + + override fun setOnClickListener(listener: OnClickListener?) { + button.setOnClickListener(listener) + } + + fun resetValue() { + button.setText(R.string.select_hint) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/enums/Platform.kt b/app/src/main/java/br/com/concrete/tentacle/data/enums/Platform.kt new file mode 100644 index 00000000..e89cbd58 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/enums/Platform.kt @@ -0,0 +1,17 @@ +package br.com.concrete.tentacle.data.enums + +import br.com.concrete.tentacle.utils.PLATFORM_NINTENDO_3DS_ABBREV +import br.com.concrete.tentacle.utils.PLATFORM_NINTENDO_SWITCH_ABBREV +import br.com.concrete.tentacle.utils.PLATFORM_PS3_ABBREV +import br.com.concrete.tentacle.utils.PLATFORM_PS4_ABBREV +import br.com.concrete.tentacle.utils.PLATFORM_XBOX_360_ABBREV +import br.com.concrete.tentacle.utils.PLATFORM_XBOX_ONE_ABBREV + +enum class Platform(val platformName: String) { + PS3(PLATFORM_PS3_ABBREV), + PS4(PLATFORM_PS4_ABBREV), + XBOXONE(PLATFORM_XBOX_ONE_ABBREV), + XBOX360(PLATFORM_XBOX_360_ABBREV), + NINTENDOSWITCH(PLATFORM_NINTENDO_SWITCH_ABBREV), + NINTENDO3DS(PLATFORM_NINTENDO_3DS_ABBREV); +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/eventPublisher/EventPublisher.kt b/app/src/main/java/br/com/concrete/tentacle/data/eventPublisher/EventPublisher.kt new file mode 100644 index 00000000..0306e4bc --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/eventPublisher/EventPublisher.kt @@ -0,0 +1,26 @@ +package br.com.concrete.tentacle.data.eventPublisher + +import br.com.concrete.tentacle.utils.SingleEvent +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.Disposable +import io.reactivex.functions.Consumer +import io.reactivex.subjects.BehaviorSubject + +class EventPublisher : EventPublisherContract { + + private val sourceSubject: BehaviorSubject = BehaviorSubject.create() + + override fun subscribe(contract: Consumer): Disposable { + return sourceSubject + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(contract) + } + + override fun publish(value: Any) { + sourceSubject.onNext(SingleEvent(value)) + } + + override fun onComplete() { + sourceSubject.onComplete() + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/eventPublisher/EventPublisherContract.kt b/app/src/main/java/br/com/concrete/tentacle/data/eventPublisher/EventPublisherContract.kt new file mode 100644 index 00000000..ee0279e0 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/eventPublisher/EventPublisherContract.kt @@ -0,0 +1,10 @@ +package br.com.concrete.tentacle.data.eventPublisher + +import io.reactivex.disposables.Disposable +import io.reactivex.functions.Consumer + +interface EventPublisherContract { + fun subscribe(contract: Consumer): Disposable + fun publish(value: Any) + fun onComplete() +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/interfaces/CallBack.kt b/app/src/main/java/br/com/concrete/tentacle/data/interfaces/CallBack.kt new file mode 100644 index 00000000..45d5b442 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/interfaces/CallBack.kt @@ -0,0 +1,5 @@ +package br.com.concrete.tentacle.data.interfaces + +interface CallBack { + fun changeBottomBar(actionNameId: Int, navigateId: Int) +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/ActiveLoan.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/ActiveLoan.kt new file mode 100644 index 00000000..025ca20b --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/ActiveLoan.kt @@ -0,0 +1,53 @@ +package br.com.concrete.tentacle.data.models + +import android.os.Parcelable +import br.com.concrete.tentacle.extensions.toDate +import br.com.concrete.tentacle.utils.DEFAULT_PENULTIMATE_DAY +import br.com.concrete.tentacle.utils.DEFAULT_RETURN_DATE_IN_WEEKS +import br.com.concrete.tentacle.utils.ONE_HOUR +import kotlinx.android.parcel.Parcelize +import java.util.Calendar +import java.util.Date + +@Parcelize +data class ActiveLoan( + val _id: String, + val requestedAt: String, + val loanDate: String?, + val requestedByName: String?, + val requestedByState: String?, + val requestedByCity: String?, + val estimatedReturnDate: String? = null +) : Parcelable { + + companion object { + fun getDefaultReturnDate(): Calendar { + val date = Calendar.getInstance() + date.add(Calendar.WEEK_OF_MONTH, DEFAULT_RETURN_DATE_IN_WEEKS) + return date + } + } + + private fun getReturnDate(): Calendar? { + loanDate?.let { + val date = it.toDate() + date.add(Calendar.WEEK_OF_MONTH, DEFAULT_RETURN_DATE_IN_WEEKS) + return date + } ?: run { + return null + } + } + + fun isExpired(): Boolean { + getReturnDate()?.let { + val currentDate = Calendar.getInstance() + val days = daysBetweenDates(currentDate.time, it.time) + return days <= DEFAULT_PENULTIMATE_DAY + } ?: run { + return false + } + } + + private fun daysBetweenDates(currentDate: Date, loanDate: Date) = + ((loanDate.time - currentDate.time + ONE_HOUR) / (ONE_HOUR * 24)) +} diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/ActiveMedia.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/ActiveMedia.kt new file mode 100644 index 00000000..d88fe7c2 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/ActiveMedia.kt @@ -0,0 +1,3 @@ +package br.com.concrete.tentacle.data.models + +class ActiveMedia(val active: Boolean = true) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/BaseModel.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/BaseModel.kt new file mode 100644 index 00000000..4fd371e2 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/BaseModel.kt @@ -0,0 +1,7 @@ +package br.com.concrete.tentacle.data.models + +data class BaseModel( + val message: List, + val data: D, + val count: Int = 0 +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/CityResponse.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/CityResponse.kt new file mode 100644 index 00000000..62e56696 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/CityResponse.kt @@ -0,0 +1,6 @@ +package br.com.concrete.tentacle.data.models + +data class CityResponse( + val cities: List, + val _id: String +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/ErrorResponse.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/ErrorResponse.kt new file mode 100644 index 00000000..7f00a03a --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/ErrorResponse.kt @@ -0,0 +1,13 @@ +package br.com.concrete.tentacle.data.models + +import android.text.TextUtils +import br.com.concrete.tentacle.utils.DEFAULT_EXCEPTION_STATUS_CODE + +data class ErrorResponse( + var message: ArrayList = ArrayList(), + var messageInt: ArrayList = ArrayList(), + var statusCode: Int = DEFAULT_EXCEPTION_STATUS_CODE, + var updateUrl: String? = null +) { + override fun toString() = TextUtils.join(".\n", message) +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/ForgotPassword.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/ForgotPassword.kt new file mode 100644 index 00000000..789e4c1d --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/ForgotPassword.kt @@ -0,0 +1,3 @@ +package br.com.concrete.tentacle.data.models + +data class ForgotPassword(val email: String) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/Game.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/Game.kt new file mode 100644 index 00000000..8520ad59 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/Game.kt @@ -0,0 +1,45 @@ +package br.com.concrete.tentacle.data.models + +import android.os.Parcelable +import br.com.concrete.tentacle.data.models.game.Cover +import br.com.concrete.tentacle.data.models.game.GameMode +import br.com.concrete.tentacle.data.models.game.Genre +import br.com.concrete.tentacle.data.models.game.Screenshot +import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class Game( + val _id: String = String(), + @SerializedName("id") val remoteGameId: Int? = null, + @SerializedName("name", alternate = ["title"]) + val name: String = String(), + @SerializedName("aggregated_rating") + val rating: Float? = .0f, + @SerializedName("first_release_date") + val releaseDate: String? = null, + val summary: String? = null, + @SerializedName("game_modes") + val gameModes: List? = null, + val genres: List? = null, + val cover: Cover? = null, + val screenshots: List? = null, + val mediaNintendo3dsCount: Int = 0, + val mediaNintendoSwitchCount: Int = 0, + val mediaPs3Count: Int = 0, + val mediaPs4Count: Int = 0, + val mediaXbox360Count: Int = 0, + val mediaXboxOneCount: Int = 0 + +) : Parcelable { + + companion object { + + const val ID_EMPTY_GAME = "-1" + + fun getEmptyGame(): Game = Game( + _id = ID_EMPTY_GAME, + name = "" + ) + } +} diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/GameData.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/GameData.kt new file mode 100644 index 00000000..852579fb --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/GameData.kt @@ -0,0 +1,10 @@ +package br.com.concrete.tentacle.data.models + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class GameData( + val _id: String, + val name: String? +) : Parcelable diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/GameRequest.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/GameRequest.kt new file mode 100644 index 00000000..f30f459b --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/GameRequest.kt @@ -0,0 +1,6 @@ +package br.com.concrete.tentacle.data.models + +data class GameRequest( + private val name: String? = null, + private val id: Int? = null +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/GameResponse.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/GameResponse.kt new file mode 100644 index 00000000..f9ff0a45 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/GameResponse.kt @@ -0,0 +1,6 @@ +package br.com.concrete.tentacle.data.models + +data class GameResponse( + val list: ArrayList, + val count: Int +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/LoanActionRequest.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/LoanActionRequest.kt new file mode 100644 index 00000000..c9303e80 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/LoanActionRequest.kt @@ -0,0 +1,3 @@ +package br.com.concrete.tentacle.data.models + +data class LoanActionRequest(private val action: String) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/LoansListResponse.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/LoansListResponse.kt new file mode 100644 index 00000000..05be8280 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/LoansListResponse.kt @@ -0,0 +1,8 @@ +package br.com.concrete.tentacle.data.models + +import br.com.concrete.tentacle.data.models.library.loan.LoanResponse + +class LoansListResponse( + val list: List, + val count: Int +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/Media.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/Media.kt new file mode 100644 index 00000000..5cc479b4 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/Media.kt @@ -0,0 +1,34 @@ +package br.com.concrete.tentacle.data.models + +import android.os.Parcelable +import br.com.concrete.tentacle.data.enums.Platform +import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class Media( + val _id: String, + val platform: Platform, + val activeLoan: ActiveLoan?, + @SerializedName("gameData") + val game: Game?, + val active: Boolean = true +) : Parcelable { + + companion object { + const val ID_EMPTY_MEDIA = "-1" + + fun getEmptyMedia(): Media = Media( + ID_EMPTY_MEDIA, + Platform.PS4, + ActiveLoan(ID_EMPTY_MEDIA, + "", + "", + "", + "", + "" + ), + Game.getEmptyGame() + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/MediaRequest.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/MediaRequest.kt new file mode 100644 index 00000000..d5b967fe --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/MediaRequest.kt @@ -0,0 +1,6 @@ +package br.com.concrete.tentacle.data.models + +data class MediaRequest( + val platform: String, + val game: String +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/MediaResponse.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/MediaResponse.kt new file mode 100644 index 00000000..b03d1f30 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/MediaResponse.kt @@ -0,0 +1,6 @@ +package br.com.concrete.tentacle.data.models + +class MediaResponse( + val list: ArrayList, + val count: Int +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/MessageReturn.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/MessageReturn.kt new file mode 100644 index 00000000..a1b7f7bf --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/MessageReturn.kt @@ -0,0 +1,5 @@ +package br.com.concrete.tentacle.data.models + +data class MessageReturn( + private val message: List +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/Owner.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/Owner.kt new file mode 100644 index 00000000..ccea4498 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/Owner.kt @@ -0,0 +1,10 @@ +package br.com.concrete.tentacle.data.models + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class Owner( + private val _id: String, + private val name: String +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/PasswordRecovery.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/PasswordRecovery.kt new file mode 100644 index 00000000..8f167ffe --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/PasswordRecovery.kt @@ -0,0 +1,7 @@ +package br.com.concrete.tentacle.data.models + +data class PasswordRecovery( + val email: String, + val token: String, + val password: String +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/QueryParameters.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/QueryParameters.kt new file mode 100644 index 00000000..07eb03a4 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/QueryParameters.kt @@ -0,0 +1,19 @@ +package br.com.concrete.tentacle.data.models + +import android.text.TextUtils + +data class QueryParameters( + var id: String? = null, + var name: String? = null, + var active: Boolean = true, + var mediaOwner: String? = null, + var mediaId: String? = null, + var mediaPlatform: ArrayList? = null, + var limit: Int? = 15, + var page: Int = 0, // First page as default page + var showHistory: Boolean = false +) { + override fun toString(): String { + return if (mediaPlatform != null) TextUtils.join(",", mediaPlatform) ?: "" else "" + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/RememberDeliveryResponse.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/RememberDeliveryResponse.kt new file mode 100644 index 00000000..5b4befe0 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/RememberDeliveryResponse.kt @@ -0,0 +1,15 @@ +package br.com.concrete.tentacle.data.models + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class RequestedBy( + val name: String +) : Parcelable + +@Parcelize +data class RememberDeliveryResponse( + val _id: String, + val requestedBy: RequestedBy +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/RequestLogin.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/RequestLogin.kt new file mode 100644 index 00000000..782608ab --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/RequestLogin.kt @@ -0,0 +1,6 @@ +package br.com.concrete.tentacle.data.models + +data class RequestLogin( + val email: String, + val password: String +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/RequestRefreshToken.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/RequestRefreshToken.kt new file mode 100644 index 00000000..f7267e3c --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/RequestRefreshToken.kt @@ -0,0 +1,5 @@ +package br.com.concrete.tentacle.data.models + +data class RequestRefreshToken( + private val refreshToken: String +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/RequestUpdateToken.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/RequestUpdateToken.kt new file mode 100644 index 00000000..ebe5b40d --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/RequestUpdateToken.kt @@ -0,0 +1,5 @@ +package br.com.concrete.tentacle.data.models + +data class RequestUpdateToken( + private val deviceToken: String? +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/Session.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/Session.kt new file mode 100644 index 00000000..f47f2349 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/Session.kt @@ -0,0 +1,7 @@ +package br.com.concrete.tentacle.data.models + +data class Session( + val accessToken: String, + val refreshToken: String, + val tokenType: String +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/State.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/State.kt new file mode 100644 index 00000000..f5d4deba --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/State.kt @@ -0,0 +1,13 @@ +package br.com.concrete.tentacle.data.models + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class State( + val _id: String, + var initials: String, + var name: String +) : Parcelable { + override fun toString() = "$initials - $name" +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/StateResponse.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/StateResponse.kt new file mode 100644 index 00000000..d0a7afd4 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/StateResponse.kt @@ -0,0 +1,5 @@ +package br.com.concrete.tentacle.data.models + +data class StateResponse( + val list: List +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/StatusLiveData.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/StatusLiveData.kt new file mode 100644 index 00000000..246b48a1 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/StatusLiveData.kt @@ -0,0 +1,10 @@ +package br.com.concrete.tentacle.data.models + +import androidx.lifecycle.LiveData + +class StatusLiveData : LiveData>() { + + public override fun postValue(value: ViewStateModel?) { + super.postValue(value) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/User.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/User.kt new file mode 100644 index 00000000..c85bfe32 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/User.kt @@ -0,0 +1,16 @@ +package br.com.concrete.tentacle.data.models + +import java.io.Serializable + +data class User( + val _id: String = String(), + var name: String, + val email: String = String(), + val phone: String = String(), + var password: String, + var state: State, + var city: String, + var createdAt: String = String(), + var updatedAt: String = String(), + var internalImage: String = String() +) : Serializable \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/UserRequest.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/UserRequest.kt new file mode 100644 index 00000000..04665220 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/UserRequest.kt @@ -0,0 +1,12 @@ +package br.com.concrete.tentacle.data.models + +data class UserRequest( + val name: String = String(), + val email: String = String(), + val phone: String = String(), + val password: String? = String(), + val state: String = String(), + val city: String = String(), + val deviceToken: String? = null, + val stateObj: State? = null +) \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/ViewStateModel.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/ViewStateModel.kt new file mode 100644 index 00000000..ff18d1dd --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/ViewStateModel.kt @@ -0,0 +1,12 @@ +package br.com.concrete.tentacle.data.models + +data class ViewStateModel ( + val status: Status, + val model: T? = null, + val errors: ErrorResponse? = null, + var filtering: Boolean = false +) { + enum class Status { + LOADING, SUCCESS, ERROR + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/filter/FilterItem.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/filter/FilterItem.kt new file mode 100644 index 00000000..ee68904e --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/filter/FilterItem.kt @@ -0,0 +1,11 @@ +package br.com.concrete.tentacle.data.models.filter + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class FilterItem( + val title: String, + val icon: String, + val subItems: List +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/filter/SubItem.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/filter/SubItem.kt new file mode 100644 index 00000000..273c8666 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/filter/SubItem.kt @@ -0,0 +1,12 @@ +package br.com.concrete.tentacle.data.models.filter + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class SubItem( + var queryType: String, + val queryParameter: String, + val name: String, + var isChecked: Boolean = false +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/game/Cover.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/game/Cover.kt new file mode 100644 index 00000000..8cd2d7e0 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/game/Cover.kt @@ -0,0 +1,9 @@ +package br.com.concrete.tentacle.data.models.game + +import com.google.gson.annotations.SerializedName +import java.io.Serializable + +data class Cover( + @SerializedName("image_id") + val imageId: String? +) : Serializable \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/game/GameMode.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/game/GameMode.kt new file mode 100644 index 00000000..71b67471 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/game/GameMode.kt @@ -0,0 +1,32 @@ +package br.com.concrete.tentacle.data.models.game + +import android.os.Parcelable +import br.com.concrete.tentacle.R +import br.com.concrete.tentacle.utils.GAME_MODE_CO_OPERATIVE +import br.com.concrete.tentacle.utils.GAME_MODE_MMO +import br.com.concrete.tentacle.utils.GAME_MODE_MULTI_PLAYER +import br.com.concrete.tentacle.utils.GAME_MODE_SINGLE_PLAYER +import br.com.concrete.tentacle.utils.GAME_MODE_SPLIT_SCREEN +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class GameMode( + val slug: String?, + val name: String? +) : Parcelable { + + fun getIconResource(): Int? { + var icon: Int? = null + slug?.let { + icon = when (it) { + GAME_MODE_SINGLE_PLAYER -> R.drawable.ic_game_mode_single_player + GAME_MODE_MULTI_PLAYER -> R.drawable.ic_game_mode_multiplayer + GAME_MODE_CO_OPERATIVE -> R.drawable.ic_game_mode_coperative + GAME_MODE_MMO -> R.drawable.ic_game_mode_mmo + GAME_MODE_SPLIT_SCREEN -> R.drawable.ic_game_mode_split_screen + else -> null + } + } + return icon + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/game/Genre.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/game/Genre.kt new file mode 100644 index 00000000..ba2da0d6 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/game/Genre.kt @@ -0,0 +1,9 @@ +package br.com.concrete.tentacle.data.models.game + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class Genre( + val name: String? +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/game/Screenshot.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/game/Screenshot.kt new file mode 100644 index 00000000..9e196db4 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/game/Screenshot.kt @@ -0,0 +1,14 @@ +package br.com.concrete.tentacle.data.models.game + +import android.os.Parcelable +import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class Screenshot( + val id: String, + val height: Int, + val width: Int, + @SerializedName("image_id") + val imageId: String +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/br/com/concrete/tentacle/data/models/library/Library.kt b/app/src/main/java/br/com/concrete/tentacle/data/models/library/Library.kt new file mode 100644 index 00000000..0aa19c46 --- /dev/null +++ b/app/src/main/java/br/com/concrete/tentacle/data/models/library/Library.kt @@ -0,0 +1,30 @@ +package br.com.concrete.tentacle.data.models.library + +import android.os.Parcelable +import br.com.concrete.tentacle.data.models.game.Cover +import br.com.concrete.tentacle.data.models.game.Screenshot +import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class Library( + val _id: String, + val mediaNintendo3ds: List, + val mediaNintendoSwitch: List, + val mediaPs3: List, + val mediaPs4: List, + val mediaXbox360: List, + val mediaXboxOne: List, + val mediaNintendo3dsCount: Int, + val mediaNintendoSwitchCount: Int, + val mediaPs3Count: Int, + val mediaPs4Count: Int, + val mediaXbox360Count: Int, + val mediaXboxOneCount: Int, + + @SerializedName("title", alternate = ["name"]) + val name: String, + val cover: Cover? = null, + val videos: List