Nested Part exceptions should bubble up.

This commit is contained in:
Jesse Brault 2023-02-16 13:53:50 +01:00
parent a6264eb823
commit c958cf1427
5 changed files with 71 additions and 15 deletions

View File

@ -56,14 +56,13 @@ class GspPartRenderer implements PartRenderer {
text: text, text: text,
urlBuilder: new PathBasedUrlBuilder(targetPath, siteSpec.baseUrl) urlBuilder: new PathBasedUrlBuilder(targetPath, siteSpec.baseUrl)
]) ])
new Tuple2<>([], result.toString()) new Tuple2<>(embeddedPartDiagnostics, result.toString())
} catch (Exception e) { } catch (Exception e) {
def diagnostic = new Diagnostic( new Tuple2<>(
[*embeddedPartDiagnostics, new Diagnostic(
"An exception occurred while rendering part ${ part.path }:\n${ e }", "An exception occurred while rendering part ${ part.path }:\n${ e }",
e e
) )],
new Tuple2<>(
[diagnostic, *embeddedPartDiagnostics],
'' ''
) )
} }

View File

@ -29,8 +29,8 @@ class GspSpecialPageRenderer implements SpecialPageRenderer {
Map globals, Map globals,
String targetPath String targetPath
) { ) {
try {
Collection<Diagnostic> diagnostics = [] Collection<Diagnostic> diagnostics = []
try {
def result = engine.createTemplate(specialPage.text).make([ def result = engine.createTemplate(specialPage.text).make([
globals: globals, globals: globals,
logger: LoggerFactory.getLogger("SpecialPage(${ specialPage.path })"), logger: LoggerFactory.getLogger("SpecialPage(${ specialPage.path })"),
@ -51,7 +51,7 @@ class GspSpecialPageRenderer implements SpecialPageRenderer {
]) ])
new Tuple2<>(diagnostics, result.toString()) new Tuple2<>(diagnostics, result.toString())
} catch (Exception e) { } 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)], '')
} }
} }

View File

@ -32,17 +32,14 @@ class GspTemplateRenderer implements TemplateRenderer {
Map globals, Map globals,
String targetPath String targetPath
) { ) {
def diagnostics = []
try { try {
Collection<Diagnostic> diagnostics = [] def embeddableText = new EmbeddableText(text, globals, diagnostics.&addAll)
def onDiagnostics = { Collection<Diagnostic> partDiagnostics ->
diagnostics.addAll(partDiagnostics)
}
def embeddableText = new EmbeddableText(text, globals, onDiagnostics)
def result = engine.createTemplate(template.text).make([ def result = engine.createTemplate(template.text).make([
frontMatter: frontMatter, frontMatter: frontMatter,
globals: globals, globals: globals,
logger: LoggerFactory.getLogger("Template(${ template.path })"), 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, path: text.path,
siteSpec: siteSpec, siteSpec: siteSpec,
tagBuilder: new DynamicTagBuilder(), tagBuilder: new DynamicTagBuilder(),
@ -52,7 +49,7 @@ class GspTemplateRenderer implements TemplateRenderer {
]) ])
new Tuple2<>(diagnostics, result.toString()) new Tuple2<>(diagnostics, result.toString())
} catch (Exception e) { } 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)], '')
} }
} }

View File

@ -10,10 +10,12 @@ import org.mockito.junit.jupiter.MockitoExtension
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory 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.assertEmptyDiagnostics
import static com.jessebrault.ssg.testutil.DiagnosticsUtil.getDiagnosticsMessageSupplier import static com.jessebrault.ssg.testutil.DiagnosticsUtil.getDiagnosticsMessageSupplier
import static com.jessebrault.ssg.text.TextMocks.renderableText import static com.jessebrault.ssg.text.TextMocks.renderableText
import static org.junit.jupiter.api.Assertions.assertEquals 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.junit.jupiter.api.Assertions.assertTrue
import static org.mockito.ArgumentMatchers.anyString import static org.mockito.ArgumentMatchers.anyString
import static org.mockito.Mockito.mockStatic 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)
}
} }

View File

@ -1,7 +1,9 @@
package com.jessebrault.ssg.testutil package com.jessebrault.ssg.testutil
import com.jessebrault.ssg.Diagnostic 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 import static org.junit.jupiter.api.Assertions.assertTrue
class DiagnosticsUtil { class DiagnosticsUtil {
@ -21,4 +23,10 @@ class DiagnosticsUtil {
assertTrue(result.v1.isEmpty(), getDiagnosticsMessageSupplier(result.v1)) assertTrue(result.v1.isEmpty(), getDiagnosticsMessageSupplier(result.v1))
} }
static void assertDiagnosticException(Class<? extends Exception> expectedException, Diagnostic diagnostic) {
assertInstanceOf(expectedException, diagnostic.exception, {
"Incorrect diagnostic exception class; message: ${ diagnostic.message }"
})
}
} }