From c958cf1427bd94cece6a4854a3209fbae008783e Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Thu, 16 Feb 2023 13:53:50 +0100 Subject: [PATCH] Nested Part exceptions should bubble up. --- .../ssg/part/GspPartRenderer.groovy | 11 ++-- .../specialpage/GspSpecialPageRenderer.groovy | 4 +- .../ssg/template/GspTemplateRenderer.groovy | 11 ++-- .../ssg/part/GspPartRendererTests.groovy | 52 +++++++++++++++++++ .../ssg/testutil/DiagnosticsUtil.groovy | 8 +++ 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/lib/src/main/groovy/com/jessebrault/ssg/part/GspPartRenderer.groovy b/lib/src/main/groovy/com/jessebrault/ssg/part/GspPartRenderer.groovy index 79e1661..d3bd1dd 100644 --- a/lib/src/main/groovy/com/jessebrault/ssg/part/GspPartRenderer.groovy +++ b/lib/src/main/groovy/com/jessebrault/ssg/part/GspPartRenderer.groovy @@ -56,14 +56,13 @@ class GspPartRenderer implements PartRenderer { text: text, urlBuilder: new PathBasedUrlBuilder(targetPath, siteSpec.baseUrl) ]) - new Tuple2<>([], result.toString()) + new Tuple2<>(embeddedPartDiagnostics, result.toString()) } catch (Exception e) { - def diagnostic = new Diagnostic( - "An exception occurred while rendering part ${ part.path }:\n${ e }", - e - ) new Tuple2<>( - [diagnostic, *embeddedPartDiagnostics], + [*embeddedPartDiagnostics, new Diagnostic( + "An exception occurred while rendering part ${ part.path }:\n${ e }", + e + )], '' ) } diff --git a/lib/src/main/groovy/com/jessebrault/ssg/specialpage/GspSpecialPageRenderer.groovy b/lib/src/main/groovy/com/jessebrault/ssg/specialpage/GspSpecialPageRenderer.groovy index b555d5d..9b78a70 100644 --- a/lib/src/main/groovy/com/jessebrault/ssg/specialpage/GspSpecialPageRenderer.groovy +++ b/lib/src/main/groovy/com/jessebrault/ssg/specialpage/GspSpecialPageRenderer.groovy @@ -29,8 +29,8 @@ class GspSpecialPageRenderer implements SpecialPageRenderer { Map globals, String targetPath ) { + Collection diagnostics = [] try { - Collection diagnostics = [] def result = engine.createTemplate(specialPage.text).make([ globals: globals, logger: LoggerFactory.getLogger("SpecialPage(${ specialPage.path })"), @@ -51,7 +51,7 @@ class GspSpecialPageRenderer implements SpecialPageRenderer { ]) new Tuple2<>(diagnostics, result.toString()) } catch (Exception e) { - new Tuple2<>([new Diagnostic("An exception occurred while rendering specialPage ${ specialPage.path }:\n${ e }", e)], '') + new Tuple2<>([*diagnostics, new Diagnostic("An exception occurred while rendering specialPage ${ specialPage.path }:\n${ e }", e)], '') } } diff --git a/lib/src/main/groovy/com/jessebrault/ssg/template/GspTemplateRenderer.groovy b/lib/src/main/groovy/com/jessebrault/ssg/template/GspTemplateRenderer.groovy index 9f4f61f..997bbce 100644 --- a/lib/src/main/groovy/com/jessebrault/ssg/template/GspTemplateRenderer.groovy +++ b/lib/src/main/groovy/com/jessebrault/ssg/template/GspTemplateRenderer.groovy @@ -32,17 +32,14 @@ class GspTemplateRenderer implements TemplateRenderer { Map globals, String targetPath ) { + def diagnostics = [] try { - Collection diagnostics = [] - def onDiagnostics = { Collection partDiagnostics -> - diagnostics.addAll(partDiagnostics) - } - def embeddableText = new EmbeddableText(text, globals, onDiagnostics) + def embeddableText = new EmbeddableText(text, globals, diagnostics.&addAll) def result = engine.createTemplate(template.text).make([ frontMatter: frontMatter, globals: globals, logger: LoggerFactory.getLogger("Template(${ template.path })"), - parts: new EmbeddablePartsMap(parts, siteSpec, globals, onDiagnostics, embeddableText, text.path, targetPath), + parts: new EmbeddablePartsMap(parts, siteSpec, globals, diagnostics.&addAll, embeddableText, text.path, targetPath), path: text.path, siteSpec: siteSpec, tagBuilder: new DynamicTagBuilder(), @@ -52,7 +49,7 @@ class GspTemplateRenderer implements TemplateRenderer { ]) new Tuple2<>(diagnostics, result.toString()) } catch (Exception e) { - new Tuple2<>([new Diagnostic("An exception occurred while rendering Template ${ template.path }:\n${ e }", e)], '') + new Tuple2<>([*diagnostics, new Diagnostic("An exception occurred while rendering Template ${ template.path }:\n${ e }", e)], '') } } diff --git a/lib/src/test/groovy/com/jessebrault/ssg/part/GspPartRendererTests.groovy b/lib/src/test/groovy/com/jessebrault/ssg/part/GspPartRendererTests.groovy index 068a4e8..833671a 100644 --- a/lib/src/test/groovy/com/jessebrault/ssg/part/GspPartRendererTests.groovy +++ b/lib/src/test/groovy/com/jessebrault/ssg/part/GspPartRendererTests.groovy @@ -10,10 +10,12 @@ import org.mockito.junit.jupiter.MockitoExtension import org.slf4j.Logger import org.slf4j.LoggerFactory +import static com.jessebrault.ssg.testutil.DiagnosticsUtil.assertDiagnosticException import static com.jessebrault.ssg.testutil.DiagnosticsUtil.assertEmptyDiagnostics import static com.jessebrault.ssg.testutil.DiagnosticsUtil.getDiagnosticsMessageSupplier import static com.jessebrault.ssg.text.TextMocks.renderableText import static org.junit.jupiter.api.Assertions.assertEquals +import static org.junit.jupiter.api.Assertions.assertInstanceOf import static org.junit.jupiter.api.Assertions.assertTrue import static org.mockito.ArgumentMatchers.anyString import static org.mockito.Mockito.mockStatic @@ -219,4 +221,54 @@ class GspPartRendererTests { } } + @Test + void nestedPartDiagnosticBubblesUp() { + def nestedProblemPart = new Part( + 'nestedProblem.gsp', + new PartType([], this.renderer), + '<% throw new RuntimeException() %>' + ) + def callerPart = new Part('caller.gsp', null, '<% parts["nestedProblem.gsp"].render() %>') + def r = this.renderer.render( + callerPart, + [:], + new SiteSpec('', ''), + [:], + null, + [callerPart, nestedProblemPart], + '', + '' + ) + assertEquals(1, r.v1.size()) + assertDiagnosticException(RuntimeException, r.v1[0]) + assertEquals('', r.v2) + } + + @Test + void nestedPartIsBlankWhenThrowingExceptionButCallerRendered() { + def nestedProblemPart = new Part( + 'nestedProblem.gsp', + new PartType([], this.renderer), + '<% throw new RuntimeException() %>' + ) + def callerPart = new Part( + 'caller.gsp', + null, + 'Hello, World!<% parts["nestedProblem.gsp"].render() %>' + ) + def r = this.renderer.render( + callerPart, + [:], + new SiteSpec('', ''), + [:], + null, + [callerPart, nestedProblemPart], + '', + '' + ) + assertEquals(1, r.v1.size()) + assertDiagnosticException(RuntimeException, r.v1[0]) + assertEquals('Hello, World!', r.v2) + } + } diff --git a/lib/src/testFixtures/groovy/com/jessebrault/ssg/testutil/DiagnosticsUtil.groovy b/lib/src/testFixtures/groovy/com/jessebrault/ssg/testutil/DiagnosticsUtil.groovy index 6405933..b1ee858 100644 --- a/lib/src/testFixtures/groovy/com/jessebrault/ssg/testutil/DiagnosticsUtil.groovy +++ b/lib/src/testFixtures/groovy/com/jessebrault/ssg/testutil/DiagnosticsUtil.groovy @@ -1,7 +1,9 @@ package com.jessebrault.ssg.testutil import com.jessebrault.ssg.Diagnostic +import com.jessebrault.ssg.text.ExcerptGetter +import static org.junit.jupiter.api.Assertions.assertInstanceOf import static org.junit.jupiter.api.Assertions.assertTrue class DiagnosticsUtil { @@ -21,4 +23,10 @@ class DiagnosticsUtil { assertTrue(result.v1.isEmpty(), getDiagnosticsMessageSupplier(result.v1)) } + static void assertDiagnosticException(Class expectedException, Diagnostic diagnostic) { + assertInstanceOf(expectedException, diagnostic.exception, { + "Incorrect diagnostic exception class; message: ${ diagnostic.message }" + }) + } + }