weeks of bullshit
This commit is contained in:
+39
@@ -0,0 +1,39 @@
|
||||
package dev.relism.ext.webbundler;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class AssetsSourceTest {
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
@Test
|
||||
void filesystemSource_loadsAssetsAndIndex() throws Exception {
|
||||
Path webRoot = tempDir.resolve("web");
|
||||
Path dist = webRoot.resolve("dist");
|
||||
Files.createDirectories(dist);
|
||||
Files.writeString(dist.resolve("index.html"), "<html>ok</html>");
|
||||
Files.writeString(dist.resolve("app.abcd1234.js"), "console.log(1)");
|
||||
|
||||
AssetsSource source = FilesystemAssetsSource.of(Path.of("dist"));
|
||||
AssetCatalog catalog = source.load(new AssetLoadRequest("/app", "index.html", RuntimeEnvironment.PROD, webRoot));
|
||||
|
||||
assertNotNull(catalog.index());
|
||||
AssetEntry js = catalog.find("/app/app.abcd1234.js");
|
||||
assertNotNull(js);
|
||||
assertTrue(js.immutable());
|
||||
}
|
||||
|
||||
@Test
|
||||
void classpathSource_missingManifestFailsFast() {
|
||||
AssetsSource source = ClasspathAssetsSource.of("missing-root");
|
||||
IllegalStateException ex = assertThrows(IllegalStateException.class,
|
||||
() -> source.load(new AssetLoadRequest("/", "index.html", RuntimeEnvironment.PROD, Path.of("."))));
|
||||
assertTrue(ex.getMessage().contains("manifest"));
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package dev.relism.ext.webbundler;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class CommandSafetyPolicyTest {
|
||||
@Test
|
||||
void block_mode_rejectsUnknownBinary() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder()
|
||||
.commandSafetyMode(CommandSafetyMode.BLOCK)
|
||||
.safeCommandRegistry(List.of("npm"))
|
||||
.build();
|
||||
CommandSafetyPolicy policy = new CommandSafetyPolicy(cfg);
|
||||
assertThrows(IllegalStateException.class, () -> policy.check(List.of("sh", "-c", "echo nope")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void allow_mode_permitsUnknownBinary() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder()
|
||||
.commandSafetyMode(CommandSafetyMode.ALLOW)
|
||||
.safeCommandRegistry(List.of("npm"))
|
||||
.build();
|
||||
CommandSafetyPolicy policy = new CommandSafetyPolicy(cfg);
|
||||
assertDoesNotThrow(() -> policy.check(List.of("custom", "run")));
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package dev.relism.ext.webbundler;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class InstallCacheTest {
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
@Test
|
||||
void lockHashChanges_areDetected() throws Exception {
|
||||
Path lockfile = tempDir.resolve("package-lock.json");
|
||||
Files.writeString(lockfile, "{\"a\":1}");
|
||||
|
||||
InstallCache cache = new InstallCache(tempDir);
|
||||
assertTrue(cache.lockChanged(lockfile));
|
||||
cache.writeLockHash(lockfile);
|
||||
assertFalse(cache.lockChanged(lockfile));
|
||||
|
||||
Files.writeString(lockfile, "{\"a\":2}");
|
||||
assertTrue(cache.lockChanged(lockfile));
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package dev.relism.ext.webbundler;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModeResolverTest {
|
||||
private final ModeResolver resolver = new ModeResolver();
|
||||
|
||||
@Test
|
||||
void prod_mode_isAlwaysProd() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder()
|
||||
.runtimeMode(RuntimeMode.PROD)
|
||||
.build();
|
||||
assertEquals(RuntimeEnvironment.PROD, resolver.resolve(cfg));
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package dev.relism.ext.webbundler;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class PackageManagerAdapterTest {
|
||||
@Test
|
||||
void pnpm_hasFrozenInstallCommand() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder()
|
||||
.packageManager(PackageManager.PNPM)
|
||||
.build();
|
||||
PackageManagerAdapter adapter = new PackageManagerAdapter(cfg);
|
||||
assertTrue(adapter.installCommand().get(0).startsWith("pnpm"));
|
||||
assertEquals("--frozen-lockfile", adapter.installCommand().get(2));
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package dev.relism.ext.webbundler;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class WebBundlerConfigTest {
|
||||
@Test
|
||||
void defaults_areSane() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder().build();
|
||||
assertEquals(RuntimeMode.AUTODETECT, cfg.runtimeMode());
|
||||
assertEquals(OperationMode.ORCHESTRATE_ONLY, cfg.operationMode());
|
||||
assertEquals(InstallPolicy.AUTO_IF_LOCK_HASH_CHANGED, cfg.installPolicy());
|
||||
assertEquals(LoggingMode.MERGED, cfg.loggingMode());
|
||||
assertEquals(CommandSafetyMode.WARN, cfg.commandSafetyMode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void packageManager_setsLockfileInWatchList() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder()
|
||||
.packageManager(PackageManager.PNPM)
|
||||
.build();
|
||||
assertTrue(cfg.watchList().contains("pnpm-lock.yaml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void basePath_isNormalized() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder().basePath("app/").build();
|
||||
assertEquals("/app", cfg.basePath());
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidPort_throws() {
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
WebBundlerConfig.builder().devPort(0).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
void assetsFromFilesystem_setsFilesystemSource() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder()
|
||||
.webRoot(Path.of("frontend"))
|
||||
.assetsFromFilesystem(Path.of("build"))
|
||||
.watchList(List.of("package.json"))
|
||||
.build();
|
||||
assertTrue(cfg.assetsSource() instanceof FilesystemAssetsSource);
|
||||
}
|
||||
|
||||
@Test
|
||||
void assetsFromClasspath_setsClasspathSource() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder()
|
||||
.assetsFromClasspath("web/dist")
|
||||
.build();
|
||||
assertTrue(cfg.assetsSource() instanceof ClasspathAssetsSource);
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package dev.relism.ext.webbundler;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class WebBundlerExtensionDevGuardTest {
|
||||
@Test
|
||||
void classpathSourceInDev_isRejected() {
|
||||
WebBundlerConfig cfg = WebBundlerConfig.builder()
|
||||
.assetsFromClasspath("web/dist")
|
||||
.build();
|
||||
|
||||
assertThrows(IllegalStateException.class, () -> WebBundlerExtension.validateDevAssetsSource(cfg));
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package dev.relism.ext.webbundler;
|
||||
|
||||
import dev.relism.extension.FlashApp;
|
||||
import dev.relism.extension.FlashConfiguration;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.net.ServerSocket;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class WebBundlerExtensionIntegrationTest {
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
private FlashApp app;
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
if (app != null) app.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
void prodMode_servesAssetsAndFallback_withoutBreakingBackendRoutes() throws Exception {
|
||||
Path webRoot = tempDir.resolve("web");
|
||||
Path dist = webRoot.resolve("dist");
|
||||
Files.createDirectories(dist);
|
||||
Files.writeString(dist.resolve("index.html"), "<html>spa</html>");
|
||||
Files.writeString(dist.resolve("app.js"), "console.log('ok');");
|
||||
|
||||
int port;
|
||||
try (ServerSocket s = new ServerSocket(0)) {
|
||||
port = s.getLocalPort();
|
||||
}
|
||||
|
||||
WebBundlerConfig config = WebBundlerConfig.builder()
|
||||
.runtimeMode(RuntimeMode.PROD)
|
||||
.operationMode(OperationMode.MANAGED)
|
||||
.webRoot(webRoot)
|
||||
.assetsFromFilesystem(Path.of("dist"))
|
||||
.basePath("/app")
|
||||
.build();
|
||||
|
||||
app = FlashApp.create(FlashConfiguration.builder().port(port).host("127.0.0.1").build());
|
||||
app.install(new WebBundlerExtension(config));
|
||||
app.get("/api/ping", (req, res) -> "pong");
|
||||
app.start();
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpResponse<String> backend = client.send(
|
||||
HttpRequest.newBuilder(URI.create("http://127.0.0.1:" + port + "/api/ping")).GET().build(),
|
||||
HttpResponse.BodyHandlers.ofString()
|
||||
);
|
||||
assertEquals(200, backend.statusCode());
|
||||
assertEquals("pong", backend.body());
|
||||
|
||||
HttpResponse<String> asset = client.send(
|
||||
HttpRequest.newBuilder(URI.create("http://127.0.0.1:" + port + "/app/app.js")).GET().build(),
|
||||
HttpResponse.BodyHandlers.ofString()
|
||||
);
|
||||
assertEquals(200, asset.statusCode());
|
||||
assertTrue(asset.body().contains("console.log"));
|
||||
|
||||
HttpResponse<String> fallback = client.send(
|
||||
HttpRequest.newBuilder(URI.create("http://127.0.0.1:" + port + "/app/some/client/route")).GET().build(),
|
||||
HttpResponse.BodyHandlers.ofString()
|
||||
);
|
||||
assertEquals(200, fallback.statusCode());
|
||||
assertTrue(fallback.body().contains("spa"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user