1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-20 00:39:08 -05:00

Add sonarqube (#37)

This commit is contained in:
Mikołaj Pich 2017-11-26 16:32:33 +01:00 committed by Rafał Borcz
parent 9ee0ca3010
commit 647ed08460
39 changed files with 277 additions and 148 deletions

View File

@ -30,10 +30,10 @@ jobs:
<<: *general_cache_key <<: *general_cache_key
- run: - run:
name: Setup environment name: Setup environment
command: ./gradlew --no-daemon --stacktrace dependencies || true command: ./gradlew dependencies --no-daemon --stacktrace --console=plain -PdisablePreDex || true
- run: - run:
name: Initial build name: Initial build
command: ./gradlew --no-daemon --stacktrace assembleDebug -PdisablePreDex command: ./gradlew -x test -x lint build assembleDebug --no-daemon --stacktrace --console=plain -PdisablePreDex
- store_artifacts: - store_artifacts:
path: ./app/build/outputs/apk/ path: ./app/build/outputs/apk/
destination: apks/ destination: apks/
@ -54,12 +54,16 @@ jobs:
<<: *general_cache_key <<: *general_cache_key
- run: - run:
name: Run lint name: Run lint
command: ./gradlew --no-daemon --stacktrace lint command: ./gradlew lint --no-daemon --stacktrace --console=plain -PdisablePreDex
- store_artifacts: - store_artifacts:
path: ./app/build/reports/ path: ./app/build/reports/
destination: lint_reports/app/ destination: lint_reports/app/
- store_test_results: - store_test_results:
path: ./app/build/reports/ path: ./app/build/reports/
- persist_to_workspace:
root: *workspace_root
paths:
- "./app/build/reports/lint-results.xml"
app-test: app-test:
<<: *container_config <<: *container_config
@ -69,15 +73,10 @@ jobs:
<<: *general_cache_key <<: *general_cache_key
- run: - run:
name: Run app tests name: Run app tests
command: ./gradlew --no-daemon --stacktrace :app:test command: ./gradlew :app:test :app:jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
- run: - run:
name: Upload unit code coverage to codecov name: Upload unit code coverage to codecov
command: | command: bash <(curl -s https://codecov.io/bash) -F app
./gradlew --no-daemon --stacktrace :app:jacocoTestReport
bash <(curl -s https://codecov.io/bash) -F app
- run:
name: Upload code coverage to codacy
command: ./gradlew --no-daemon --stacktrace :app:codacyUpload
- store_artifacts: - store_artifacts:
path: ./app/build/reports/tests/ path: ./app/build/reports/tests/
destination: tests_reports/ destination: tests_reports/
@ -86,6 +85,10 @@ jobs:
destination: coverage_reports/ destination: coverage_reports/
- store_test_results: - store_test_results:
path: ./app/build/test-results path: ./app/build/test-results
- persist_to_workspace:
root: *workspace_root
paths:
- "./app/build/jacoco"
api-test: api-test:
<<: *container_config <<: *container_config
@ -95,15 +98,10 @@ jobs:
<<: *general_cache_key <<: *general_cache_key
- run: - run:
name: Run api tests name: Run api tests
command: ./gradlew --no-daemon --stacktrace :api:test command: ./gradlew :api:test :api:jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
- run: - run:
name: Upload unit code coverage to codecov name: Upload code coverage to codecov
command: | command: bash <(curl -s https://codecov.io/bash) -F api
./gradlew --no-daemon --stacktrace :api:jacocoTestReport
bash <(curl -s https://codecov.io/bash) -F api
- run:
name: Upload code coverage to codacy
command: ./gradlew --no-daemon --stacktrace :api:codacyUpload
- store_artifacts: - store_artifacts:
path: ./api/build/reports/tests/ path: ./api/build/reports/tests/
destination: tests_reports/ destination: tests_reports/
@ -112,6 +110,10 @@ jobs:
destination: coverage_reports/ destination: coverage_reports/
- store_test_results: - store_test_results:
path: ./api/build/test-results path: ./api/build/test-results
- persist_to_workspace:
root: *workspace_root
paths:
- "./api/build/jacoco"
instrumented: instrumented:
<<: *container_config <<: *container_config
@ -137,7 +139,7 @@ jobs:
command: ./gradlew clean --no-daemon --stacktrace --console=plain -PdisablePreDex command: ./gradlew clean --no-daemon --stacktrace --console=plain -PdisablePreDex
- run: - run:
name: Run instrumented tests name: Run instrumented tests
command: ./gradlew connectedAndroidTest --no-daemon --stacktrace --console=plain -PdisablePreDex command: ./gradlew createDebugCoverageReport --no-daemon --stacktrace --console=plain -PdisablePreDex
- run: - run:
name: Collect logs from emulator name: Collect logs from emulator
command: adb logcat -d > ./app/build/reports/logcat_emulator.txt command: adb logcat -d > ./app/build/reports/logcat_emulator.txt
@ -149,6 +151,23 @@ jobs:
destination: reports destination: reports
- store_test_results: - store_test_results:
path: ./app/build/outputs/androidTest-results/connected/ path: ./app/build/outputs/androidTest-results/connected/
- persist_to_workspace:
root: *workspace_root
paths:
- "./app/build/outputs/code-coverage/connected"
sonarcube:
<<: *container_config
steps:
- *attach_workspace
- restore_cache:
<<: *general_cache_key
- run:
name: Prepare coverage report
command: ./gradlew jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
- run:
name: Run sonarqube runner
command: ./gradlew -x test -x lint sonarqube -Dsonar.host.url=$SONAR_HOST -Dsonar.organization=$SONAR_ORG -Dsonar.login=$SONAR_KEY -Dsonar.branch.name=$CIRCLE_BRANCH --no-daemon --stacktrace --console=plain -PdisablePreDex
workflows: workflows:
version: 2 version: 2
@ -168,3 +187,12 @@ workflows:
- instrumented: - instrumented:
requires: requires:
- build - build
requires:
- build
- sonarcube:
requires:
- build
- lint
- app-test
- api-test
- instrumented

View File

@ -1,19 +0,0 @@
coverage:
range: 60..100
status:
project:
default: off
unit:
target: 20%
flags: unit
instrumented:
target: 20%
flags: instrumented
flags:
unit:
paths:
- app/src/main/io/github/wulkanowy
instrumented:
paths:
- app/src/main/io/github/wulkanowy

View File

@ -4,8 +4,9 @@
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![Dependency Status](https://www.versioneye.com/user/projects/5969ff0b0fb24f004f8c711b/badge.svg?style=flat-square)](https://www.versioneye.com/user/projects/5969ff0b0fb24f004f8c711b) [![Dependency Status](https://www.versioneye.com/user/projects/5969ff0b0fb24f004f8c711b/badge.svg?style=flat-square)](https://www.versioneye.com/user/projects/5969ff0b0fb24f004f8c711b)
[![CircleCI](https://img.shields.io/circleci/project/github/wulkanowy/wulkanowy.svg?style=flat-square)](https://circleci.com/gh/wulkanowy/wulkanowy) [![CircleCI](https://img.shields.io/circleci/project/github/wulkanowy/wulkanowy.svg?style=flat-square)](https://circleci.com/gh/wulkanowy/wulkanowy)
[![Build Status](https://www.bitrise.io/app/daeff1893f3c8128.svg?token=Hjm1ACamk86JDeVVJHOeqQ&branch=master)](https://www.bitrise.io/app/daeff1893f3c8128) [![Bitrise](https://img.shields.io/bitrise/daeff1893f3c8128/master.svg?token=Hjm1ACamk86JDeVVJHOeqQ&style=flat-square)](https://www.bitrise.io/app/daeff1893f3c8128)
[![BCH compliance](https://bettercodehub.com/edge/badge/wulkanowy/wulkanowy?branch=master)](https://bettercodehub.com/) [![BCH compliance](https://bettercodehub.com/edge/badge/wulkanowy/wulkanowy?branch=master)](https://bettercodehub.com/)
[![Bintray](https://img.shields.io/bintray/v/wulkanowy/wulkanowy/api.svg?style=flat-square)](https://bintray.com/wulkanowy/wulkanowy/api)
[Pobierz wersję rozwojową](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/app-debug.apk) [Pobierz wersję rozwojową](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/app-debug.apk)

36
android-sonarqube.gradle Normal file
View File

@ -0,0 +1,36 @@
apply plugin: 'org.sonarqube'
sonarqube {
//noinspection GroovyAssignabilityCheck
properties {
def files = fileTree("${rootProject.projectDir}/api/build/libs/").filter { it.isFile() }.files.name
def libraries = project.android.sdkDirectory.getPath() + "/platforms/android-27/android.jar," +
"${project.rootDir}/api/build/libs/" + files[0]
property "sonar.projectName", GROUP_ID + ":app"
property "sonar.projectKey", GROUP_ID + ":app"
property "sonar.sources", "src/main/java"
property "sonar.exclusions", "build/**,**/*.png,*.iml, **/*generated*," +
"src/**/entities/*.java, src/androidTest/**/entities/*.java"
property "sonar.import_unknown_files", true
// Defines where the java files are
property "sonar.binaries", "build/intermediates/classes/debug"
property "sonar.libraries", libraries
// Defines where the xml files are
property "sonar.java.binaries", "build/intermediates/classes/debug"
property "sonar.java.libraries", libraries
// Analyze tests classes
property "sonar.tests", "src/test/java, src/androidTest/java"
property "sonar.java.test.binaries", "build/intermediates/classes/debug"
property "sonar.java.test.libraries", libraries
property "sonar.java.coveragePlugin", "jacoco"
property "sonar.android.lint.report", "build/reports/lint-results.xml"
property "sonar.jacoco.reportPaths", fileTree(dir: project.projectDir, includes: ['**/*.exec', '**/*.ec'])
}
}

View File

@ -1,6 +1,6 @@
apply plugin: 'java-library' apply plugin: 'java-library'
apply plugin: 'org.sonarqube'
apply plugin: 'jacoco' apply plugin: 'jacoco'
apply plugin: "io.github.ddimtirov.codacy"
apply plugin: 'com.jfrog.bintray' apply plugin: 'com.jfrog.bintray'
apply plugin: 'com.github.dcendents.android-maven' apply plugin: 'com.github.dcendents.android-maven'
@ -8,9 +8,9 @@ sourceCompatibility = "1.7"
targetCompatibility = "1.7" targetCompatibility = "1.7"
ext { ext {
PUBLISH_GROUP_ID = 'io.github.wulkanowy' PUBLISH_GROUP_ID = GROUP_ID
PUBLISH_ARTIFACT_ID = 'api' PUBLISH_ARTIFACT_ID = 'api'
PUBLISH_VERSION = '0.1.0' PUBLISH_VERSION = System.getenv('GIT_TAG')
} }
test { test {
@ -21,6 +21,12 @@ test {
} }
} }
jacocoTestReport {
reports {
xml.enabled true
}
}
dependencies { dependencies {
implementation 'org.jsoup:jsoup:1.10.3' implementation 'org.jsoup:jsoup:1.10.3'
implementation 'org.apache.commons:commons-lang3:3.6' implementation 'org.apache.commons:commons-lang3:3.6'
@ -29,9 +35,18 @@ dependencies {
testImplementation 'org.mockito:mockito-core:2.11.0' testImplementation 'org.mockito:mockito-core:2.11.0'
} }
version = PUBLISH_VERSION
group = GROUP_ID
sonarqube {
properties {
property "sonar.projectName", GROUP_ID + ":api"
property "sonar.projectKey", GROUP_ID + ":wulkanowy-api"
}
}
def siteUrl = 'https://github.com/wulkanowy/wulkanowy' def siteUrl = 'https://github.com/wulkanowy/wulkanowy'
def gitUrl = 'https://github.com/wulkanowy/wulkanowy.git' def gitUrl = 'https://github.com/wulkanowy/wulkanowy.git'
version = '0.1.0'
bintray { bintray {
user = System.getenv('BINTRAY_USER') user = System.getenv('BINTRAY_USER')
@ -45,10 +60,11 @@ bintray {
vcsUrl = gitUrl vcsUrl = gitUrl
labels = ['aar', 'android', 'wulkanowy', 'api'] labels = ['aar', 'android', 'wulkanowy', 'api']
publicDownloadNumbers = true publicDownloadNumbers = true
publish = true
version { version {
name = '0.1.0' name = PUBLISH_VERSION
vcsTag = '0.1.0' vcsTag = PUBLISH_VERSION
released = new Date() released = new Date()
} }
} }
@ -83,3 +99,18 @@ install {
} }
} }
} }
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}

View File

@ -5,19 +5,19 @@ import java.util.Map;
public class Cookies { public class Cookies {
private Map<String, String> cookies = new HashMap<>(); private Map<String, String> jar = new HashMap<>();
public Map<String, String> getItems() { public Map<String, String> getItems() {
return cookies; return jar;
} }
public Cookies setItems(Map<String, String> items) { public Cookies setItems(Map<String, String> items) {
this.cookies = items; this.jar = items;
return this; return this;
} }
public Cookies addItems(Map<String, String> items) { public Cookies addItems(Map<String, String> items) {
this.cookies.putAll(items); this.jar.putAll(items);
return this; return this;
} }
} }

View File

@ -16,7 +16,9 @@ public class StudentAndParent extends Api {
private String baseUrl = "https://uonetplus-opiekun.vulcan.net.pl/{symbol}/{ID}/"; private String baseUrl = "https://uonetplus-opiekun.vulcan.net.pl/{symbol}/{ID}/";
private String gradesPageUrl = baseUrl + "Oceny/Wszystkie"; private static final String SYMBOL_PLACEHOLDER = "{symbol}";
private static final String GRADES_PAGE_URL = "Oceny/Wszystkie";
private String symbol; private String symbol;
@ -33,7 +35,7 @@ public class StudentAndParent extends Api {
} }
public String getGradesPageUrl() { public String getGradesPageUrl() {
return gradesPageUrl; return baseUrl + GRADES_PAGE_URL;
} }
public String getBaseUrl() { public String getBaseUrl() {
@ -58,11 +60,11 @@ public class StudentAndParent extends Api {
public String getSnpPageUrl() throws IOException, NotLoggedInErrorException { public String getSnpPageUrl() throws IOException, NotLoggedInErrorException {
if (null != getId()) { if (null != getId()) {
return getBaseUrl().replace("{symbol}", getSymbol()).replace("{ID}", getId()); return getBaseUrl().replace(SYMBOL_PLACEHOLDER, getSymbol()).replace("{ID}", getId());
} }
// get url to uonetplus-opiekun.vulcan.net.pl // get url to uonetplus-opiekun.vulcan.net.pl
Document startPage = getPageByUrl(getStartPageUrl().replace("{symbol}", getSymbol())); Document startPage = getPageByUrl(getStartPageUrl().replace(SYMBOL_PLACEHOLDER, getSymbol()));
Element studentTileLink = startPage.select(".panel.linkownia.pracownik.klient > a").first(); Element studentTileLink = startPage.select(".panel.linkownia.pracownik.klient > a").first();
if (null == studentTileLink) { if (null == studentTileLink) {
@ -92,7 +94,7 @@ public class StudentAndParent extends Api {
public Document getSnPPageDocument(String url) throws IOException { public Document getSnPPageDocument(String url) throws IOException {
return getPageByUrl(getBaseUrl() return getPageByUrl(getBaseUrl()
.replace("{symbol}", getSymbol()) .replace(SYMBOL_PLACEHOLDER, getSymbol())
.replace("{ID}", getId()) + url); .replace("{ID}", getId()) + url);
} }

View File

@ -14,7 +14,7 @@ public class ExamsWeek {
private final StudentAndParent snp; private final StudentAndParent snp;
private final String examsPageUrl = "Sprawdziany.mvc/Terminarz?rodzajWidoku=2&data="; private static final String EXAMS_PAGE_URL = "Sprawdziany.mvc/Terminarz?rodzajWidoku=2&data=";
public ExamsWeek(StudentAndParent snp) { public ExamsWeek(StudentAndParent snp) {
this.snp = snp; this.snp = snp;
@ -25,7 +25,7 @@ public class ExamsWeek {
} }
public Week getWeek(String tick, final boolean onlyNotEmpty) throws IOException { public Week getWeek(String tick, final boolean onlyNotEmpty) throws IOException {
Document examsPage = snp.getSnPPageDocument(examsPageUrl + tick); Document examsPage = snp.getSnPPageDocument(EXAMS_PAGE_URL + tick);
Elements examsDays = examsPage.select(".mainContainer > div:not(.navigation)"); Elements examsDays = examsPage.select(".mainContainer > div:not(.navigation)");
List<Day> days = new ArrayList<>(); List<Day> days = new ArrayList<>();

View File

@ -16,13 +16,12 @@ import java.util.regex.Pattern;
import io.github.wulkanowy.api.Semester; import io.github.wulkanowy.api.Semester;
import io.github.wulkanowy.api.StudentAndParent; import io.github.wulkanowy.api.StudentAndParent;
import io.github.wulkanowy.api.login.LoginErrorException;
public class GradesList { public class GradesList {
private StudentAndParent snp = null; private StudentAndParent snp = null;
private String gradesPageUrl = "Oceny/Wszystkie?details=2&okres="; private static final String GRADES_PAGE_URL = "Oceny/Wszystkie?details=2&okres=";
private List<Grade> grades = new ArrayList<>(); private List<Grade> grades = new ArrayList<>();
@ -31,10 +30,10 @@ public class GradesList {
} }
public String getGradesPageUrl() { public String getGradesPageUrl() {
return gradesPageUrl; return GRADES_PAGE_URL;
} }
public List<Grade> getAll() throws IOException, LoginErrorException, ParseException { public List<Grade> getAll() throws IOException, ParseException {
return getAll(""); return getAll("");
} }

View File

@ -14,14 +14,14 @@ public class SubjectsList {
private StudentAndParent snp = null; private StudentAndParent snp = null;
private String subjectsPageUrl = "Oceny/Wszystkie?details=1"; private static final String SUBJECTS_PAGE_URL = "Oceny/Wszystkie?details=1";
public SubjectsList(StudentAndParent snp) { public SubjectsList(StudentAndParent snp) {
this.snp = snp; this.snp = snp;
} }
public List<Subject> getAll() throws IOException { public List<Subject> getAll() throws IOException {
Document subjectPage = snp.getSnPPageDocument(subjectsPageUrl); Document subjectPage = snp.getSnPPageDocument(SUBJECTS_PAGE_URL);
Elements rows = subjectPage.select(".ocenyZwykle-table > tbody > tr"); Elements rows = subjectPage.select(".ocenyZwykle-table > tbody > tr");

View File

@ -90,7 +90,7 @@ public class Login extends Api {
Elements els = Jsoup.parse(certificate.replaceAll(":", ""), "", Parser.xmlParser()) Elements els = Jsoup.parse(certificate.replaceAll(":", ""), "", Parser.xmlParser())
.select("[AttributeName=\"UserInstance\"] samlAttributeValue"); .select("[AttributeName=\"UserInstance\"] samlAttributeValue");
if (0 == els.size()) { if (els.isEmpty()) {
return ""; return "";
} }

View File

@ -13,23 +13,23 @@ public class AchievementsList {
private StudentAndParent snp = null; private StudentAndParent snp = null;
private List<String> achievementsList = new ArrayList<>(); private List<String> achievements = new ArrayList<>();
private String notesPageUrl = "UwagiOsiagniecia.mvc/Wszystkie"; private static final String NOTES_PAGE_URL = "UwagiOsiagniecia.mvc/Wszystkie";
public AchievementsList(StudentAndParent snp) { public AchievementsList(StudentAndParent snp) {
this.snp = snp; this.snp = snp;
} }
public List<String> getAllAchievements() throws IOException { public List<String> getAllAchievements() throws IOException {
Element pageFragment = snp.getSnPPageDocument(notesPageUrl) Element pageFragment = snp.getSnPPageDocument(NOTES_PAGE_URL)
.select(".mainContainer > div").get(1); .select(".mainContainer > div").get(1);
Elements items = pageFragment.select("article"); Elements items = pageFragment.select("article");
for (Element item : items) { for (Element item : items) {
achievementsList.add(item.text()); achievements.add(item.text());
} }
return achievementsList; return achievements;
} }
} }

View File

@ -13,23 +13,23 @@ public class NotesList {
private StudentAndParent snp = null; private StudentAndParent snp = null;
private List<Note> notesList = new ArrayList<>(); private List<Note> notes = new ArrayList<>();
private String notesPageUrl = "UwagiOsiagniecia.mvc/Wszystkie"; private static final String NOTES_PAGE_URL = "UwagiOsiagniecia.mvc/Wszystkie";
public NotesList(StudentAndParent snp) { public NotesList(StudentAndParent snp) {
this.snp = snp; this.snp = snp;
} }
public List<Note> getAllNotes() throws IOException { public List<Note> getAllNotes() throws IOException {
Element pageFragment = snp.getSnPPageDocument(notesPageUrl) Element pageFragment = snp.getSnPPageDocument(NOTES_PAGE_URL)
.select(".mainContainer > div").get(0); .select(".mainContainer > div").get(0);
Elements items = pageFragment.select("article"); Elements items = pageFragment.select("article");
Elements dates = pageFragment.select("h2"); Elements dates = pageFragment.select("h2");
int index = 0; int index = 0;
for (Element item : items) { for (Element item : items) {
notesList.add(new Note() notes.add(new Note()
.setDate(dates.get(index++).text()) .setDate(dates.get(index++).text())
.setTeacher(snp.getRowDataChildValue(item, 1)) .setTeacher(snp.getRowDataChildValue(item, 1))
.setCategory(snp.getRowDataChildValue(item, 2)) .setCategory(snp.getRowDataChildValue(item, 2))
@ -37,6 +37,6 @@ public class NotesList {
); );
} }
return notesList; return notes;
} }
} }

View File

@ -10,14 +10,14 @@ public class SchoolInfo {
private StudentAndParent snp = null; private StudentAndParent snp = null;
private String schoolPageUrl = "Szkola.mvc/Nauczyciele"; private static final String SCHOOL_PAGE_URL = "Szkola.mvc/Nauczyciele";
public SchoolInfo(StudentAndParent snp) { public SchoolInfo(StudentAndParent snp) {
this.snp = snp; this.snp = snp;
} }
public SchoolData getSchoolData() throws IOException { public SchoolData getSchoolData() throws IOException {
Element e = snp.getSnPPageDocument(schoolPageUrl) Element e = snp.getSnPPageDocument(SCHOOL_PAGE_URL)
.select(".mainContainer > article").get(0); .select(".mainContainer > article").get(0);
return new SchoolData() return new SchoolData()

View File

@ -14,14 +14,14 @@ public class TeachersInfo {
private StudentAndParent snp = null; private StudentAndParent snp = null;
private String schoolPageUrl = "Szkola.mvc/Nauczyciele"; private static final String SCHOOL_PAGE_URL = "Szkola.mvc/Nauczyciele";
public TeachersInfo(StudentAndParent snp) { public TeachersInfo(StudentAndParent snp) {
this.snp = snp; this.snp = snp;
} }
public TeachersData getTeachersData() throws IOException { public TeachersData getTeachersData() throws IOException {
Document doc = snp.getSnPPageDocument(schoolPageUrl); Document doc = snp.getSnPPageDocument(SCHOOL_PAGE_URL);
Elements rows = doc.select(".mainContainer > table tbody tr"); Elements rows = doc.select(".mainContainer > table tbody tr");
String description = doc.select(".mainContainer > p").first().text(); String description = doc.select(".mainContainer > p").first().text();

View File

@ -9,24 +9,23 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import io.github.wulkanowy.api.StudentAndParent; import io.github.wulkanowy.api.StudentAndParent;
import io.github.wulkanowy.api.login.LoginErrorException;
public class Timetable { public class Timetable {
private StudentAndParent snp; private StudentAndParent snp;
private String timetablePageUrl = "Lekcja.mvc/PlanLekcji?data="; private static final String TIMETABLE_PAGE_URL = "Lekcja.mvc/PlanLekcji?data=";
public Timetable(StudentAndParent snp) { public Timetable(StudentAndParent snp) {
this.snp = snp; this.snp = snp;
} }
public Week getWeekTable() throws IOException, LoginErrorException { public Week getWeekTable() throws IOException {
return getWeekTable(""); return getWeekTable("");
} }
public Week getWeekTable(String tick) throws IOException { public Week getWeekTable(String tick) throws IOException {
Element table = snp.getSnPPageDocument(timetablePageUrl + tick) Element table = snp.getSnPPageDocument(TIMETABLE_PAGE_URL + tick)
.select(".mainContainer .presentData").first(); .select(".mainContainer .presentData").first();
Elements tableHeaderCells = table.select("thead th"); Elements tableHeaderCells = table.select("thead th");
@ -100,14 +99,14 @@ public class Timetable {
lesson.setRoom(spans.get(3).text()); lesson.setRoom(spans.get(3).text());
} }
lesson = getLessonGroupDivisionInfo(lesson, spans); addGroupDivisionInfo(lesson, spans);
lesson = getLessonTypeInfo(lesson, spans); adTypeInfo(lesson, spans);
lesson = getLessonDescriptionInfo(lesson, spans); addDescriptionInfo(lesson, spans);
return lesson; return lesson;
} }
private Lesson getLessonGroupDivisionInfo(Lesson lesson, Elements e) { private void addGroupDivisionInfo(Lesson lesson, Elements e) {
if ((4 == e.size() && (e.first().attr("class").equals("")) || if ((4 == e.size() && (e.first().attr("class").equals("")) ||
(5 == e.size() && e.first().hasClass(Lesson.CLASS_NEW_MOVED_IN_OR_CHANGED)))) { (5 == e.size() && e.first().hasClass(Lesson.CLASS_NEW_MOVED_IN_OR_CHANGED)))) {
lesson.setDivisionIntoGroups(true); lesson.setDivisionIntoGroups(true);
@ -118,11 +117,9 @@ public class Timetable {
lesson.setTeacher(e.get(2).text()); lesson.setTeacher(e.get(2).text());
lesson.setRoom(e.get(3).text()); lesson.setRoom(e.get(3).text());
} }
return lesson;
} }
private Lesson getLessonTypeInfo(Lesson lesson, Elements e) { private void adTypeInfo(Lesson lesson, Elements e) {
if (e.first().hasClass(Lesson.CLASS_MOVED_OR_CANCELED)) { if (e.first().hasClass(Lesson.CLASS_MOVED_OR_CANCELED)) {
lesson.setMovedOrCanceled(true); lesson.setMovedOrCanceled(true);
} else if (e.first().hasClass(Lesson.CLASS_NEW_MOVED_IN_OR_CHANGED)) { } else if (e.first().hasClass(Lesson.CLASS_NEW_MOVED_IN_OR_CHANGED)) {
@ -135,17 +132,13 @@ public class Timetable {
|| e.first().attr("class").equals("")) { || e.first().attr("class").equals("")) {
lesson.setRealized(true); lesson.setRealized(true);
} }
return lesson;
} }
private Lesson getLessonDescriptionInfo(Lesson lesson, Elements e) { private void addDescriptionInfo(Lesson lesson, Elements e) {
if ((4 == e.size() || 5 == e.size()) if ((4 == e.size() || 5 == e.size())
&& (e.first().hasClass(Lesson.CLASS_MOVED_OR_CANCELED) && (e.first().hasClass(Lesson.CLASS_MOVED_OR_CANCELED)
|| e.first().hasClass(Lesson.CLASS_NEW_MOVED_IN_OR_CHANGED))) { || e.first().hasClass(Lesson.CLASS_NEW_MOVED_IN_OR_CHANGED))) {
lesson.setDescription(StringUtils.substringBetween(e.last().text(), "(", ")")); lesson.setDescription(StringUtils.substringBetween(e.last().text(), "(", ")"));
} }
return lesson;
} }
} }

View File

@ -6,15 +6,16 @@ import org.jsoup.nodes.Element;
import java.io.IOException; import java.io.IOException;
import io.github.wulkanowy.api.StudentAndParent; import io.github.wulkanowy.api.StudentAndParent;
import io.github.wulkanowy.api.login.LoginErrorException;
public class BasicInformation { public class BasicInformation {
private static Document studentDataPageDocument; private Document studentDataPageDocument;
private StudentAndParent snp; private StudentAndParent snp;
private String studentDataPageUrl = "Uczen.mvc/DanePodstawowe"; private static final String STUDENT_DATA_PAGE_URL = "Uczen.mvc/DanePodstawowe";
private static final String CONTENT_QUERY = ".mainContainer > article";
public BasicInformation(StudentAndParent snp) { public BasicInformation(StudentAndParent snp) {
this.snp = snp; this.snp = snp;
@ -22,14 +23,14 @@ public class BasicInformation {
public Document getStudentDataPageDocument() throws IOException { public Document getStudentDataPageDocument() throws IOException {
if (null == studentDataPageDocument) { if (null == studentDataPageDocument) {
studentDataPageDocument = snp.getSnPPageDocument(studentDataPageUrl); studentDataPageDocument = snp.getSnPPageDocument(STUDENT_DATA_PAGE_URL);
} }
return studentDataPageDocument; return studentDataPageDocument;
} }
public PersonalData getPersonalData() throws IOException, LoginErrorException { public PersonalData getPersonalData() throws IOException {
Element e = getStudentDataPageDocument().select(".mainContainer > article").get(0); Element e = getStudentDataPageDocument().select(CONTENT_QUERY).get(0);
String name = snp.getRowDataChildValue(e, 1); String name = snp.getRowDataChildValue(e, 1);
String[] names = name.split(" "); String[] names = name.split(" ");
@ -47,8 +48,8 @@ public class BasicInformation {
.setParentsNames(snp.getRowDataChildValue(e, 7)); .setParentsNames(snp.getRowDataChildValue(e, 7));
} }
public AddressData getAddressData() throws IOException, LoginErrorException { public AddressData getAddressData() throws IOException {
Element e = getStudentDataPageDocument().select(".mainContainer > article").get(1); Element e = getStudentDataPageDocument().select(CONTENT_QUERY).get(1);
return new AddressData() return new AddressData()
.setAddress(snp.getRowDataChildValue(e, 1)) .setAddress(snp.getRowDataChildValue(e, 1))
@ -57,8 +58,8 @@ public class BasicInformation {
} }
public ContactDetails getContactDetails() throws IOException, LoginErrorException { public ContactDetails getContactDetails() throws IOException {
Element e = getStudentDataPageDocument().select(".mainContainer > article").get(2); Element e = getStudentDataPageDocument().select(CONTENT_QUERY).get(2);
return new ContactDetails() return new ContactDetails()
.setPhoneNumber(snp.getRowDataChildValue(e, 1)) .setPhoneNumber(snp.getRowDataChildValue(e, 1))

View File

@ -13,14 +13,14 @@ public class FamilyInformation {
private StudentAndParent snp; private StudentAndParent snp;
private String studentDataPageUrl = "Uczen.mvc/DanePodstawowe"; private static final String STUDENT_DATA_PAGE_URL = "Uczen.mvc/DanePodstawowe";
public FamilyInformation(StudentAndParent snp) { public FamilyInformation(StudentAndParent snp) {
this.snp = snp; this.snp = snp;
} }
public List<FamilyMember> getFamilyMembers() throws IOException { public List<FamilyMember> getFamilyMembers() throws IOException {
Elements membersElements = snp.getSnPPageDocument(studentDataPageUrl) Elements membersElements = snp.getSnPPageDocument(STUDENT_DATA_PAGE_URL)
.select(".mainContainer > article:nth-of-type(n+4)"); .select(".mainContainer > article:nth-of-type(n+4)");
List<FamilyMember> familyMembers = new ArrayList<>(); List<FamilyMember> familyMembers = new ArrayList<>();

View File

@ -1,7 +1,7 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'jacoco-android'
apply plugin: "io.github.ddimtirov.codacy"
apply plugin: 'org.greenrobot.greendao' apply plugin: 'org.greenrobot.greendao'
apply from: '../jacoco.gradle'
apply from: '../android-sonarqube.gradle'
android { android {
compileSdkVersion 27 compileSdkVersion 27

View File

@ -86,22 +86,20 @@ public class GradesDialogFragment extends DialogFragment {
public static int colorHexToColorName(String hexColor) { public static int colorHexToColorName(String hexColor) {
switch (hexColor) { switch (hexColor) {
case "000000": { case "000000":
return R.string.color_black_text; return R.string.color_black_text;
}
case "F04C4C": { case "F04C4C":
return R.string.color_red_text; return R.string.color_red_text;
}
case "20A4F7": { case "20A4F7":
return R.string.color_blue_text; return R.string.color_blue_text;
}
case "6ECD07": { case "6ECD07":
return R.string.color_green_text; return R.string.color_green_text;
}
default: { default:
return R.string.noColor_text; return R.string.noColor_text;
} }
}
} }
} }

View File

@ -106,7 +106,7 @@ public class GradesFragment extends Fragment {
for (Subject subject : account.getSubjectList()) { for (Subject subject : account.getSubjectList()) {
List<Grade> gradeList = subject.getGradeList(); List<Grade> gradeList = subject.getGradeList();
if (gradeList.size() != 0) { if (!gradeList.isEmpty()) {
SubjectWithGrades subjectWithGrades = new SubjectWithGrades(subject.getName(), gradeList); SubjectWithGrades subjectWithGrades = new SubjectWithGrades(subject.getName(), gradeList);
subjectWithGradesList.add(subjectWithGrades); subjectWithGradesList.add(subjectWithGrades);
} }
@ -133,11 +133,12 @@ public class GradesFragment extends Fragment {
return null; return null;
} }
@Override
protected void onPostExecute(Void result) { protected void onPostExecute(Void result) {
super.onPostExecute(result); super.onPostExecute(result);
createExpList(mainView.get(), activity.get()); createExpList(mainView.get(), activity.get());
mainView.get().findViewById(R.id.loadingPanel).setVisibility(View.INVISIBLE); mainView.get().findViewById(R.id.loadingPanel).setVisibility(View.INVISIBLE);
if (subjectWithGradesList.size() == 0) { if (subjectWithGradesList.isEmpty()) {
mainView.get().findViewById(R.id.fragment_no_grades).setVisibility(View.VISIBLE); mainView.get().findViewById(R.id.fragment_no_grades).setVisibility(View.VISIBLE);
} }
} }

View File

@ -202,7 +202,7 @@ public class LoginActivity extends Activity {
|| ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText
&& !view.getClass().getName().startsWith("android.webkit.")) { && !view.getClass().getName().startsWith("android.webkit.")) {
int coordinators[] = new int[2]; int[] coordinators = new int[2];
view.getLocationOnScreen(coordinators); view.getLocationOnScreen(coordinators);
float x = ev.getRawX() + view.getLeft() - coordinators[0]; float x = ev.getRawX() + view.getLeft() - coordinators[0];
float y = ev.getRawY() + view.getTop() - coordinators[1]; float y = ev.getRawY() + view.getTop() - coordinators[1];

View File

@ -7,7 +7,11 @@ import java.util.List;
import io.github.wulkanowy.dao.entities.Grade; import io.github.wulkanowy.dao.entities.Grade;
public abstract class EntitiesCompare { public class EntitiesCompare {
private EntitiesCompare() {
throw new IllegalStateException("Utility class");
}
public static List<Grade> compareGradeList(List<Grade> newList, List<Grade> oldList) { public static List<Grade> compareGradeList(List<Grade> newList, List<Grade> oldList) {
@ -18,7 +22,7 @@ public abstract class EntitiesCompare {
List<Grade> lastList = new ArrayList<>(); List<Grade> lastList = new ArrayList<>();
for (Grade grade : addedOrUpdatedGradeList) { for (Grade grade : addedOrUpdatedGradeList) {
if (oldList.size() != 0) { if (!oldList.isEmpty()) {
grade.setRead(false); grade.setRead(false);
grade.setIsNew(true); grade.setIsNew(true);
} }

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.utilities.RootUtilities;
public class Safety extends Scrambler { public class Safety extends Scrambler {
public String encrypt(String email, String plainText, Context context) throws CryptoException, UnsupportedOperationException { public String encrypt(String email, String plainText, Context context) throws CryptoException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
loadKeyStore(); loadKeyStore();

View File

@ -32,7 +32,7 @@ public class Scrambler {
private static final String ANDROID_KEYSTORE = "AndroidKeyStore"; private static final String ANDROID_KEYSTORE = "AndroidKeyStore";
public final static String DEBUG_TAG = "WulkanowySecurity"; public static final String DEBUG_TAG = "WulkanowySecurity";
private KeyStore keyStore; private KeyStore keyStore;

View File

@ -39,8 +39,7 @@ public class VulcanSynchronization {
} }
public void firstLoginSignInStep(Context context, DaoSession daoSession) public void firstLoginSignInStep(Context context, DaoSession daoSession)
throws NotLoggedInErrorException, AccountPermissionException, IOException, CryptoException, throws NotLoggedInErrorException, AccountPermissionException, IOException, CryptoException {
UnsupportedOperationException {
if (firstAccountLogin != null && certificate != null) { if (firstAccountLogin != null && certificate != null) {
loginSession = firstAccountLogin.login(context, daoSession, certificate); loginSession = firstAccountLogin.login(context, daoSession, certificate);
} else { } else {

View File

@ -44,8 +44,7 @@ public class FirstAccountLogin {
} }
public LoginSession login(Context context, DaoSession daoSession, String certificate) public LoginSession login(Context context, DaoSession daoSession, String certificate)
throws NotLoggedInErrorException, AccountPermissionException, IOException, CryptoException, throws NotLoggedInErrorException, AccountPermissionException, IOException, CryptoException{
UnsupportedOperationException {
long userId; long userId;

View File

@ -4,7 +4,11 @@ import java.util.List;
import io.github.wulkanowy.dao.entities.Grade; import io.github.wulkanowy.dao.entities.Grade;
public abstract class AverageCalculator { public class AverageCalculator {
private AverageCalculator() {
throw new IllegalStateException("Utility class");
}
public static float calculate(List<Grade> gradeList) { public static float calculate(List<Grade> gradeList) {

View File

@ -4,7 +4,11 @@ import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
public abstract class ConnectionUtilities { public class ConnectionUtilities {
private ConnectionUtilities() {
throw new IllegalStateException("Utility class");
}
public static boolean isOnline(Context context) { public static boolean isOnline(Context context) {
ConnectivityManager connectivityManager = ConnectivityManager connectivityManager =

View File

@ -7,7 +7,11 @@ import java.util.List;
import io.github.wulkanowy.dao.entities.Grade; import io.github.wulkanowy.dao.entities.Grade;
import io.github.wulkanowy.dao.entities.Subject; import io.github.wulkanowy.dao.entities.Subject;
public abstract class ConversionVulcanObject { public class ConversionVulcanObject {
private ConversionVulcanObject() {
throw new IllegalStateException("Utility class");
}
public static List<Subject> subjectsToSubjectEntities(List<io.github.wulkanowy.api.grades.Subject> subjectList) { public static List<Subject> subjectsToSubjectEntities(List<io.github.wulkanowy.api.grades.Subject> subjectList) {

View File

@ -7,12 +7,16 @@ import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
abstract public class DateHelper { public class DateHelper {
private static final long TICKS_AT_EPOCH = 621355968000000000L; private static final long TICKS_AT_EPOCH = 621355968000000000L;
private static final long TICKS_PER_MILLISECOND = 10000; private static final long TICKS_PER_MILLISECOND = 10000;
private DateHelper() {
throw new IllegalStateException("Utility class");
}
public static long getTicks(Date date) { public static long getTicks(Date date) {
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
calendar.setTime(date); calendar.setTime(date);

View File

@ -1,11 +1,14 @@
package io.github.wulkanowy.utilities; package io.github.wulkanowy.utilities;
import android.os.Build; import android.os.Build;
import java.io.File; import java.io.File;
abstract public class RootUtilities { public class RootUtilities {
private RootUtilities() {
throw new IllegalStateException("Utility class");
}
public static boolean isRooted() { public static boolean isRooted() {
String buildTags = Build.TAGS; String buildTags = Build.TAGS;

View File

@ -10,7 +10,7 @@ import java.util.List;
import io.github.wulkanowy.dao.entities.Grade; import io.github.wulkanowy.dao.entities.Grade;
public class EntitiesCompareTest extends EntitiesCompare { public class EntitiesCompareTest {
private List<Grade> newList = new ArrayList<>(); private List<Grade> newList = new ArrayList<>();

View File

@ -8,7 +8,7 @@ import java.util.List;
import io.github.wulkanowy.dao.entities.Grade; import io.github.wulkanowy.dao.entities.Grade;
public class AverageCalculatorTest extends AverageCalculator { public class AverageCalculatorTest {
@Test @Test
public void averageTest() { public void averageTest() {

View File

@ -10,7 +10,7 @@ import org.junit.Test;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
public class ConnectionUtilitiesTest extends ConnectionUtilities { public class ConnectionUtilitiesTest {
@Test @Test
public void isOnlineTrueTest() { public void isOnlineTrueTest() {

View File

@ -9,7 +9,7 @@ import java.util.List;
import io.github.wulkanowy.api.grades.Grade; import io.github.wulkanowy.api.grades.Grade;
import io.github.wulkanowy.api.grades.Subject; import io.github.wulkanowy.api.grades.Subject;
public class ConversionVulcanObjectTest extends ConversionVulcanObject { public class ConversionVulcanObjectTest {
@Test @Test
public void subjectConversionTest() { public void subjectConversionTest() {

View File

@ -11,7 +11,7 @@ import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
public class DateHelperTest extends DateHelper { public class DateHelperTest {
@Test @Test
public void getTicksDateObjectTest() throws Exception { public void getTicksDateObjectTest() throws Exception {

View File

@ -1,5 +1,3 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
repositories { repositories {
jcenter() jcenter()
@ -8,13 +6,12 @@ buildscript {
maven { url 'https://maven.google.com' } maven { url 'https://maven.google.com' }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.0' classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
classpath 'com.dicedmelon.gradle:jacoco-android:0.1.2' classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.1"
classpath "gradle.plugin.io.github.ddimtirov:codacy-gradle-plugin:0.1.0"
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
} }
@ -31,6 +28,10 @@ subprojects {
} }
} }
ext {
GROUP_ID = "io.github.wulkanowy"
}
allprojects { allprojects {
repositories { repositories {
jcenter() jcenter()

36
jacoco.gradle Normal file
View File

@ -0,0 +1,36 @@
apply plugin: "jacoco"
jacoco {
toolVersion "0.7.4.201502262128"
}
// run ./gradlew clean createDebugCoverageReport jacocoTestReport
task jacocoTestReport(type: JacocoReport) {
group = "Reporting"
description = "Generate Jacoco coverage reports"
reports {
xml.enabled = true
html.enabled = true
}
def fileFilter = ["**/R.class",
"**/R\$*.class",
"**/BuildConfig.*",
"**/Manifest*.*",
"android/**/*.*",
"**/Lambda.class",
"**/*Lambda.class",
"**/*Lambda*.class",
"**/*Lambda*.*",
"**/*Builder.*"
]
def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter)
def mainSrc = "${project.projectDir}/src/main/java"
sourceDirectories = files([mainSrc])
classDirectories = files([debugTree])
executionData = fileTree(dir: project.projectDir, includes: ["**/*.exec" , "**/*.ec"])
}