Skip to content

Commit f7ba00e

Browse files
Merge pull request #8 from VictorGotsenko/Step07
Step07 - done. Add tests and refactored some modules: UrlCheck Url AppTest made AppSettings module for constants
2 parents bb1bde5 + d7c0a33 commit f7ba00e

17 files changed

Lines changed: 468 additions & 53 deletions

File tree

app/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,19 @@ dependencies {
4444
implementation("com.h2database:h2:2.3.232")
4545
implementation("com.zaxxer:HikariCP:6.3.0")
4646

47+
// Unirest Java
48+
implementation("com.konghq:unirest-java:3.14.5")
49+
4750
// Tests
4851
testImplementation("org.junit.jupiter:junit-jupiter:6.0.0-M1")
4952
testImplementation(platform("org.junit:junit-bom:6.0.0-M1"))
5053
testImplementation("io.javalin:javalin-testtools:6.7.0")
5154
testImplementation("org.assertj:assertj-core:4.0.0-M1")
5255
testRuntimeOnly("org.junit.platform:junit-platform-launcher:6.0.0-M1")
56+
57+
// MockWebServer » 5.1.0
58+
// testImplementation("com.squareup.okhttp3:mockwebserver:5.1.0")
59+
testImplementation("com.squareup.okhttp3:mockwebserver:4.12.0")
5360
}
5461

5562
checkstyle {

app/src/main/java/hexlet/code/App.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package hexlet.code;
22

3+
import hexlet.code.controller.UrlCheckController;
34
import hexlet.code.repository.BaseRepository;
45
import hexlet.code.controller.UrlController;
56
import hexlet.code.util.NamedRoutes;
@@ -64,7 +65,7 @@ public static Javalin getApp() throws IOException, SQLException { //
6465
Statement statement = connection.createStatement()) {
6566
statement.execute(sql);
6667
}
67-
BaseRepository.dataSource = dataSource;
68+
BaseRepository.setDataSource(dataSource);
6869

6970
Javalin app = Javalin.create(config -> {
7071
config.bundledPlugins.enableDevLogging();
@@ -78,6 +79,8 @@ public static Javalin getApp() throws IOException, SQLException { //
7879
app.get(NamedRoutes.buildPath(), UrlController::build);
7980
app.get(NamedRoutes.urlsPath(), UrlController::index);
8081
app.get(NamedRoutes.urlPath("{id}"), UrlController::show);
82+
// checks
83+
app.post(NamedRoutes.urlPathForChecks("{id}"), UrlCheckController::check);
8184

8285
return app;
8386
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package hexlet.code.controller;
2+
3+
import hexlet.code.model.Url;
4+
import hexlet.code.model.UrlCheck;
5+
import hexlet.code.repository.UrlCheckRepository;
6+
import hexlet.code.repository.UrlRepository;
7+
import hexlet.code.util.NamedRoutes;
8+
9+
import static hexlet.code.util.AppSettings.FLASH_TYPE;
10+
import static hexlet.code.util.AppSettings.FLASH_DANGER;
11+
import static hexlet.code.util.AppSettings.FLASH_SUCCESS;
12+
13+
import static hexlet.code.util.AppSettings.FLASH;
14+
import static hexlet.code.util.AppSettings.CHECK_ERROR;
15+
import static hexlet.code.util.AppSettings.PAGE_OK;
16+
import static hexlet.code.util.AppSettings.URL_BAD;
17+
18+
import io.javalin.http.Context;
19+
import io.javalin.http.NotFoundResponse;
20+
21+
import java.sql.SQLException;
22+
23+
import kong.unirest.HttpResponse;
24+
import kong.unirest.Unirest;
25+
import kong.unirest.UnirestException;
26+
import lombok.extern.slf4j.Slf4j;
27+
28+
@Slf4j
29+
public final class UrlCheckController {
30+
private UrlCheckController() {
31+
// Prevent instantiation - Sonar Warning
32+
}
33+
34+
public static void check(Context ctx) throws SQLException {
35+
Long urlId = ctx.pathParamAsClass("id", Long.class).get();
36+
Url url = UrlRepository.find(urlId)
37+
.orElseThrow(() -> new NotFoundResponse("Entity with id = " + urlId + " not found"));
38+
log.info("Получен ID: {}", urlId);
39+
try {
40+
HttpResponse<String> response = Unirest.get(url.getName()).asString();
41+
int statusCode = response.getStatus();
42+
43+
UrlCheck urlCheck = new UrlCheck(urlId, statusCode, "title", "h1", "descrip");
44+
UrlCheckRepository.save(urlCheck);
45+
46+
log.info("check saved");
47+
} catch (UnirestException e) {
48+
ctx.sessionAttribute(FLASH, URL_BAD);
49+
ctx.sessionAttribute(FLASH_TYPE, FLASH_DANGER);
50+
ctx.redirect(NamedRoutes.urlPath(urlId));
51+
52+
} catch (Exception e) {
53+
ctx.sessionAttribute(FLASH, CHECK_ERROR + e.getMessage());
54+
ctx.sessionAttribute(FLASH_TYPE, FLASH_DANGER);
55+
ctx.redirect(NamedRoutes.urlPath(urlId));
56+
}
57+
ctx.sessionAttribute(FLASH, PAGE_OK);
58+
ctx.sessionAttribute(FLASH_TYPE, FLASH_SUCCESS);
59+
ctx.redirect(NamedRoutes.urlPath(urlId));
60+
}
61+
}

app/src/main/java/hexlet/code/controller/UrlController.java

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,22 @@
44
import hexlet.code.dto.urls.UrlPage;
55
import hexlet.code.dto.urls.UrlsPage;
66
import hexlet.code.model.Url;
7+
import hexlet.code.model.UrlCheck;
8+
import hexlet.code.repository.UrlCheckRepository;
79
import hexlet.code.repository.UrlRepository;
810
import hexlet.code.util.NamedRoutes;
911

12+
import static hexlet.code.util.AppSettings.FLASH;
13+
import static hexlet.code.util.AppSettings.FLASH_DANGER;
14+
import static hexlet.code.util.AppSettings.FLASH_INFO;
15+
import static hexlet.code.util.AppSettings.FLASH_SUCCESS;
16+
import static hexlet.code.util.AppSettings.FLASH_TYPE;
17+
import static hexlet.code.util.AppSettings.FLASH_WARNING;
18+
import static hexlet.code.util.AppSettings.PAGE_ADDED;
19+
import static hexlet.code.util.AppSettings.PAGE_EXIST;
20+
import static hexlet.code.util.AppSettings.URL_BAD;
21+
import static hexlet.code.util.AppSettings.URL_EMPTY;
22+
1023
import io.javalin.http.Context;
1124
import io.javalin.http.NotFoundResponse;
1225

@@ -20,34 +33,40 @@
2033
import java.sql.SQLException;
2134
import java.time.LocalDateTime;
2235
import java.util.List;
36+
import java.util.Map;
2337

2438
import lombok.extern.slf4j.Slf4j;
2539
import org.apache.http.client.utils.URIBuilder;
2640

2741
@Slf4j
28-
public class UrlController {
42+
public final class UrlController {
43+
private UrlController() {
44+
// Sonar warning
45+
// Prevent instantiation
46+
}
47+
2948
public static void build(Context ctx) {
3049
BasePage page = new BasePage();
31-
page.setFlash(ctx.consumeSessionAttribute("flash"));
32-
page.setFlashType(ctx.consumeSessionAttribute("flash-type"));
50+
page.setFlash(ctx.consumeSessionAttribute(FLASH));
51+
page.setFlashType(ctx.consumeSessionAttribute(FLASH_TYPE));
3352
ctx.render("urls/build.jte", model("page", page));
3453
}
3554

3655
public static void create(Context ctx) throws SQLException, URISyntaxException, MalformedURLException {
3756
String name = ctx.formParamAsClass("url", String.class).get();
38-
URL unifmResourceId = null;
57+
URL unifmResourceId;
3958
try {
4059
unifmResourceId = new URI(name).toURL();
4160
} catch (Exception e) {
42-
ctx.sessionAttribute("flash", "Некорректный URL");
43-
ctx.sessionAttribute("flash-type", "danger");
61+
ctx.sessionAttribute(FLASH, URL_BAD);
62+
ctx.sessionAttribute(FLASH_TYPE, FLASH_DANGER);
4463
ctx.redirect(NamedRoutes.buildPath());
4564
return;
4665
}
4766

48-
if (name == null || name.isEmpty()) {
49-
ctx.sessionAttribute("flash", "Поле URL не должно быть пустым");
50-
ctx.sessionAttribute("flash-type", "warning");
67+
if (name.isEmpty()) {
68+
ctx.sessionAttribute(FLASH, URL_EMPTY);
69+
ctx.sessionAttribute(FLASH_TYPE, FLASH_WARNING);
5170
ctx.redirect(NamedRoutes.buildPath());
5271
return;
5372
}
@@ -62,32 +81,38 @@ public static void create(Context ctx) throws SQLException, URISyntaxException,
6281
Url newUrl = new Url(String.valueOf(url), LocalDateTime.now());
6382
UrlRepository.save(newUrl);
6483
} else {
65-
ctx.sessionAttribute("flash", "Страница уже существует");
66-
ctx.sessionAttribute("flash-type", "info");
84+
ctx.sessionAttribute(FLASH, PAGE_EXIST);
85+
ctx.sessionAttribute(FLASH_TYPE, FLASH_INFO);
6786
ctx.redirect(NamedRoutes.urlsPath());
6887
return;
6988
}
7089

71-
ctx.sessionAttribute("flash", "Страница успешно добавлена");
72-
ctx.sessionAttribute("flash-type", "success");
90+
ctx.sessionAttribute(FLASH, PAGE_ADDED);
91+
ctx.sessionAttribute(FLASH_TYPE, FLASH_SUCCESS);
7392
ctx.redirect(NamedRoutes.urlsPath());
7493
}
7594

7695
public static void index(Context ctx) throws SQLException {
7796
List<Url> urls = UrlRepository.getEntities();
78-
UrlsPage page = new UrlsPage(urls);
79-
page.setFlash(ctx.consumeSessionAttribute("flash"));
80-
page.setFlashType(ctx.consumeSessionAttribute("flash-type"));
97+
Map<Long, UrlCheck> latestChecks = UrlCheckRepository.getLastestChecks();
98+
99+
UrlsPage page = new UrlsPage(urls, latestChecks);
100+
page.setFlash(ctx.consumeSessionAttribute(FLASH));
101+
page.setFlashType(ctx.consumeSessionAttribute(FLASH_TYPE));
81102
ctx.render("urls/indexList.jte", model("page", page));
82103
}
83104

84105
public static void show(Context ctx) throws SQLException {
85106
Long id = ctx.pathParamAsClass("id", Long.class).get();
86107
Url url = UrlRepository.find(id)
87108
.orElseThrow(() -> new NotFoundResponse("Entity with id = " + id + " not found"));
109+
List<UrlCheck> urlCheckList = UrlCheckRepository.findById(id);
110+
if (!urlCheckList.isEmpty()) {
111+
url.setUrlCheckList(urlCheckList);
112+
}
88113
UrlPage page = new UrlPage(url);
89-
page.setFlash(ctx.consumeSessionAttribute("flash"));
90-
page.setFlashType(ctx.consumeSessionAttribute("flash-type"));
114+
page.setFlash(ctx.consumeSessionAttribute(FLASH));
115+
page.setFlashType(ctx.consumeSessionAttribute(FLASH_TYPE));
91116
ctx.render("urls/show.jte", model("page", page));
92117
}
93118
}

app/src/main/java/hexlet/code/dto/urls/UrlsPage.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
import hexlet.code.model.Url;
55

66
import java.util.List;
7+
import java.util.Map;
78

9+
import hexlet.code.model.UrlCheck;
810
import lombok.AllArgsConstructor;
911
import lombok.Getter;
1012

1113
@AllArgsConstructor
1214
@Getter
1315
public class UrlsPage extends BasePage {
1416
private List<Url> urls;
17+
private Map<Long, UrlCheck> latestChecks;
1518
}

app/src/main/java/hexlet/code/model/Url.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import lombok.ToString;
66

77
import java.time.LocalDateTime;
8+
import java.util.ArrayList;
9+
import java.util.List;
810

911
@Getter
1012
@Setter
@@ -13,9 +15,11 @@ public class Url {
1315
private Long id;
1416
private String name;
1517
private LocalDateTime createdAt;
18+
private List<UrlCheck> urlCheckList;
1619

1720
public Url(String name, LocalDateTime createdAt) {
1821
this.name = name;
1922
this.createdAt = createdAt;
23+
this.urlCheckList = new ArrayList<>();
2024
}
2125
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package hexlet.code.model;
2+
3+
import java.time.LocalDateTime;
4+
import lombok.Getter;
5+
import lombok.Setter;
6+
7+
@Getter
8+
@Setter
9+
public class UrlCheck {
10+
private Long id;
11+
private Long urlId;
12+
private int statusCode;
13+
private String title;
14+
private String h1;
15+
private String description;
16+
private LocalDateTime createdAt;
17+
18+
public UrlCheck(Long urlId, int statusCode, String title, String h1, String description) {
19+
this.urlId = urlId;
20+
this.title = title;
21+
this.h1 = h1;
22+
this.description = description;
23+
this.statusCode = statusCode;
24+
}
25+
}

app/src/main/java/hexlet/code/repository/BaseRepository.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,13 @@
33
import com.zaxxer.hikari.HikariDataSource;
44

55
public class BaseRepository {
6-
public static HikariDataSource dataSource;
6+
private static HikariDataSource dataSource;
7+
8+
public static HikariDataSource getDataSource() {
9+
return dataSource;
10+
}
11+
12+
public static void setDataSource(HikariDataSource dataSource) {
13+
BaseRepository.dataSource = dataSource;
14+
}
715
}

0 commit comments

Comments
 (0)