From c9f2915f02fbb6e30bd805672b8551f5baf4e262 Mon Sep 17 00:00:00 2001 From: bosecodes Date: Tue, 15 Jul 2025 20:09:39 +0530 Subject: [PATCH] added tests --- .github/workflows/ci.yml | 2 +- frontendtest/index.html | 1 + frontendtest/login.html | 1 + frontendtest/register.html | 20 +++++ pom.xml | 4 +- src/main/java/urlshortener/Server.java | 5 +- .../java/urlshortener/database/Database.java | 9 ++- .../urlshortener/service/HomePageHandler.java | 4 +- .../java/urlshortener/FakeHttpExchange.java | 71 +++++++++++++++++ src/test/java/urlshortener/ServerTest.java | 8 +- .../service/HomePageHandlerTest.java | 76 +++++++++++++++++++ .../urlshortener/service/UrlHandlerTest.java | 29 +++++++ 12 files changed, 215 insertions(+), 15 deletions(-) create mode 100644 frontendtest/index.html create mode 100644 frontendtest/login.html create mode 100644 frontendtest/register.html create mode 100644 src/test/java/urlshortener/FakeHttpExchange.java create mode 100644 src/test/java/urlshortener/service/HomePageHandlerTest.java create mode 100644 src/test/java/urlshortener/service/UrlHandlerTest.java diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ae7f8a..ef03a67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up JDK 23 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' diff --git a/frontendtest/index.html b/frontendtest/index.html new file mode 100644 index 0000000..ff39d8c --- /dev/null +++ b/frontendtest/index.html @@ -0,0 +1 @@ +

Welcome, {{username}}

\ No newline at end of file diff --git a/frontendtest/login.html b/frontendtest/login.html new file mode 100644 index 0000000..2d6d129 --- /dev/null +++ b/frontendtest/login.html @@ -0,0 +1 @@ +Login Page \ No newline at end of file diff --git a/frontendtest/register.html b/frontendtest/register.html new file mode 100644 index 0000000..9e943d3 --- /dev/null +++ b/frontendtest/register.html @@ -0,0 +1,20 @@ + + + + Register + + +

Register

+
+
+

+ +
+

+ + +
+ +

Already have an account? Login here

+ + diff --git a/pom.xml b/pom.xml index 7c571a1..9ffc60e 100644 --- a/pom.xml +++ b/pom.xml @@ -65,8 +65,8 @@ maven-compiler-plugin 3.10.1 - 23 - 23 + 17 + 17 diff --git a/src/main/java/urlshortener/Server.java b/src/main/java/urlshortener/Server.java index 59cca9c..184dcbe 100644 --- a/src/main/java/urlshortener/Server.java +++ b/src/main/java/urlshortener/Server.java @@ -18,8 +18,8 @@ public static void main(String[] args) throws Exception { // Setup H2 database in memory conn = DriverManager.getConnection(AppConfig.DB_URL, AppConfig.DB_USER, AppConfig.DB_PASS); try (Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE users (username VARCHAR(255) PRIMARY KEY, password VARCHAR(255))"); - } + stmt.execute("DROP TABLE IF EXISTS users"); + stmt.execute("CREATE TABLE users (username VARCHAR(255) PRIMARY KEY, password VARCHAR(255))"); } HttpServer server = HttpServer.create(new InetSocketAddress(AppConfig.PORT), 0); server.createContext("/register", new RegisterHandler(getConn())); @@ -27,7 +27,6 @@ public static void main(String[] args) throws Exception { server.createContext("/index", new HomePageHandler(getConn())); server.createContext("/", new HomePageHandler(getConn())); server.createContext("/shorten", new UrlHandler()); - server.createContext("/s", new RedirectHandler()); server.setExecutor(null); server.start(); diff --git a/src/main/java/urlshortener/database/Database.java b/src/main/java/urlshortener/database/Database.java index e84af0b..a57df25 100644 --- a/src/main/java/urlshortener/database/Database.java +++ b/src/main/java/urlshortener/database/Database.java @@ -1,11 +1,14 @@ package urlshortener.database; +import lombok.Setter; + import java.sql.*; public class Database { - private static final String JDBC_URL = "jdbc:h2:./shorten-db"; + @Setter + private static String jdbcUrl = "jdbc:h2:./shorten-db"; // default - static { + public static void initSchema() { try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) { stmt.executeUpdate("CREATE TABLE IF NOT EXISTS urls (" + "id IDENTITY PRIMARY KEY, " + @@ -17,7 +20,7 @@ public class Database { } public static Connection getConnection() throws SQLException { - return DriverManager.getConnection(JDBC_URL, "sa", ""); + return DriverManager.getConnection(jdbcUrl, "sa", ""); } public static void insertUrl(String shortCode, String longUrl) throws SQLException { diff --git a/src/main/java/urlshortener/service/HomePageHandler.java b/src/main/java/urlshortener/service/HomePageHandler.java index 73e242c..9cc5d6a 100644 --- a/src/main/java/urlshortener/service/HomePageHandler.java +++ b/src/main/java/urlshortener/service/HomePageHandler.java @@ -14,6 +14,7 @@ public class HomePageHandler implements HttpHandler { private static Connection conn; + String fileLocation = "frontend/index.html"; public HomePageHandler(Connection conn) { HomePageHandler.conn = conn; @@ -32,8 +33,7 @@ public void handle(HttpExchange exchange) throws IOException { exchange.sendResponseHeaders(405, -1); return; } - - String html = new String(Files.readAllBytes(Paths.get("frontend/index.html"))); + String html = new String(Files.readAllBytes(Paths.get(fileLocation))); html = html.replace("{{username}}", username); byte[] response = html.getBytes(); diff --git a/src/test/java/urlshortener/FakeHttpExchange.java b/src/test/java/urlshortener/FakeHttpExchange.java new file mode 100644 index 0000000..af762c9 --- /dev/null +++ b/src/test/java/urlshortener/FakeHttpExchange.java @@ -0,0 +1,71 @@ +package urlshortener; + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpPrincipal; +import lombok.Getter; + +import java.io.*; +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.*; + +public class FakeHttpExchange extends HttpExchange { + private final ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); + private final Headers requestHeaders = new Headers(); + private final Headers responseHeaders = new Headers(); + private final URI uri; + private final String method; + private ByteArrayOutputStream responseBody = new ByteArrayOutputStream(); + private InputStream requestBody = InputStream.nullInputStream(); + @Getter + private int statusCode; + + + public FakeHttpExchange(String method, String uri) { + this.method = method; + this.uri = URI.create(uri); + } + + @Override public Headers getRequestHeaders() { return requestHeaders; } + @Override public Headers getResponseHeaders() { return responseHeaders; } + @Override public URI getRequestURI() { return uri; } + @Override public String getRequestMethod() { return method; } + @Override public OutputStream getResponseBody() { return responseStream; } + @Override public InputStream getRequestBody() { return InputStream.nullInputStream(); } + + @Override public HttpContext getHttpContext() { return null; } + @Override public void close() {} + @Override public InetSocketAddress getRemoteAddress() { return null; } + + public String getResponseText() { + return responseBody.toString(StandardCharsets.UTF_8); + } + + @Override + public int getResponseCode() { + return 0; + } + + @Override + public void sendResponseHeaders(int code, long length) { + this.statusCode = code; + } + + @Override public InetSocketAddress getLocalAddress() { return null; } + @Override public String getProtocol() { return null; } + @Override public Object getAttribute(String s) { return null; } + @Override public void setAttribute(String s, Object o) {} + @Override public void setStreams(InputStream inputStream, OutputStream outputStream) {} + + @Override + public HttpPrincipal getPrincipal() { + return null; + } + + public void setRequestBody(String body) { + this.requestBody = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/src/test/java/urlshortener/ServerTest.java b/src/test/java/urlshortener/ServerTest.java index 2d54720..3967d4c 100644 --- a/src/test/java/urlshortener/ServerTest.java +++ b/src/test/java/urlshortener/ServerTest.java @@ -19,7 +19,7 @@ static void setupDatabase() throws Exception { // Use real in-memory H2 database for integration-style test conn = DriverManager.getConnection("jdbc:h2:mem:testdb", "sa", ""); try (Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE users (username VARCHAR(255) PRIMARY KEY, password VARCHAR(255))"); + stmt.execute("CREATE TABLE userstest (username VARCHAR(255) PRIMARY KEY, password VARCHAR(255))"); } } @@ -27,7 +27,7 @@ static void setupDatabase() throws Exception { void testUsersTableCreatedSuccessfully() throws Exception { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'USERS'"); - assertTrue(rs.next(), "Users table should exist"); + assertTrue(rs.next(), "Userstest table should exist"); } @Test @@ -40,11 +40,11 @@ void testMockedConnectionTableCreation() throws Exception { when(mockStmt.execute(anyString())).thenReturn(true); // Run the DB setup logic - mockConn.createStatement().execute("CREATE TABLE users (username VARCHAR(255) PRIMARY KEY, password VARCHAR(255))"); + mockConn.createStatement().execute("CREATE TABLE userstest (username VARCHAR(255) PRIMARY KEY, password VARCHAR(255))"); // Verify SQL execution verify(mockConn).createStatement(); - verify(mockStmt).execute("CREATE TABLE users (username VARCHAR(255) PRIMARY KEY, password VARCHAR(255))"); + verify(mockStmt).execute("CREATE TABLE userstest (username VARCHAR(255) PRIMARY KEY, password VARCHAR(255))"); } @Test diff --git a/src/test/java/urlshortener/service/HomePageHandlerTest.java b/src/test/java/urlshortener/service/HomePageHandlerTest.java new file mode 100644 index 0000000..477b11a --- /dev/null +++ b/src/test/java/urlshortener/service/HomePageHandlerTest.java @@ -0,0 +1,76 @@ +package urlshortener.service; + + +import org.junit.jupiter.api.*; +import urlshortener.FakeHttpExchange; +import urlshortener.config.AppConfig; +import urlshortener.service.HomePageHandler; + +import java.io.ByteArrayOutputStream; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.*; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import static java.nio.charset.StandardCharsets.UTF_8; + +class HomePageHandlerTest { + + Connection conn = DriverManager.getConnection("jdbc:h2:mem:testdb", "sa", ""); + + private static final String HTML_TEMPLATE = + "

Welcome, {{username}}

"; + private static final String INDEX_PATH = "frontendtest/index.html"; + + HomePageHandlerTest() throws SQLException { + } + + @BeforeAll + static void setup() throws Exception { + Files.createDirectories(Paths.get("frontendtest")); + try (PrintWriter writer = new PrintWriter(new FileWriter(INDEX_PATH))) { + writer.write(HTML_TEMPLATE); + } + } + +// @AfterAll +// static void cleanup() throws Exception { +// Files.deleteIfExists(Paths.get(INDEX_PATH)); +// Files.deleteIfExists(Paths.get("frontendtest")); +// } + + @Test + void testHomePageHandlerWithUsernameQuery() throws Exception { + FakeHttpExchange exchange = new FakeHttpExchange("GET", "/?username=sa"); + HomePageHandler handler = new HomePageHandler(conn); + handler.fileLocation = INDEX_PATH; + + handler.handle(exchange); + + // Properly read the actual HTML string from the output stream + String response = convertStreamToString((ByteArrayOutputStream) exchange.getResponseBody()); // custom method that does .toString(StandardCharsets.UTF_8) + Assertions.assertTrue(response.contains("Welcome, sa")); + } + + @Test + void testHomePageHandlerWithoutQuery() throws Exception { + FakeHttpExchange exchange = new FakeHttpExchange("GET", "/"); + HomePageHandler handler = new HomePageHandler(conn); + handler.fileLocation = INDEX_PATH; + + handler.handle(exchange); + + String response = convertStreamToString((ByteArrayOutputStream) exchange.getResponseBody()); // custom method that does .toString(StandardCharsets.UTF_8) + Assertions.assertFalse(response.contains("Welcome, sa")); + } + + public String convertStreamToString(ByteArrayOutputStream outputStream) { + if (outputStream == null) { + return ""; + } + return outputStream.toString(StandardCharsets.UTF_8); + } +} diff --git a/src/test/java/urlshortener/service/UrlHandlerTest.java b/src/test/java/urlshortener/service/UrlHandlerTest.java new file mode 100644 index 0000000..94c8fc5 --- /dev/null +++ b/src/test/java/urlshortener/service/UrlHandlerTest.java @@ -0,0 +1,29 @@ +package urlshortener.service; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import urlshortener.database.Database; + +import static org.junit.jupiter.api.Assertions.*; + +public class UrlHandlerTest { + + @BeforeAll + static void setupDatabase() { + // Use in-memory DB for isolated testing + Database.setJdbcUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1"); + Database.initSchema(); // Create `urls` table + } + + @Test + void testInsertAndRetrieveUrl() throws Exception { + String shortCode = "abc123"; + String longUrl = "https://example.com"; + + Database.insertUrl(shortCode, longUrl); + String fetched = Database.getLongUrl(shortCode); + + assertEquals(longUrl, fetched); + } + +}