From 57d3ec7b2b15e9a895e08fccedd368647622493f Mon Sep 17 00:00:00 2001 From: Jens Peters Date: Fri, 3 Nov 2023 09:27:43 +0100 Subject: [PATCH] Detect external systems by tag Replace our own heuristics based on groups. Therefore add a property "generatr.site.excludedTag" to define the name of the tag that identifies external systems. Also adjust example. --- README.md | 7 +- docs/example/workspace.dsl | 1 + .../site/generatr/StructurizrUtilities.kt | 17 +-- .../C4PlantUmlExporterWithElementLinks.kt | 6 +- .../site/generatr/site/DiagramGenerator.kt | 3 +- .../site/generatr/site/SiteGenerator.kt | 2 +- .../site/generatr/site/model/PageViewModel.kt | 2 +- .../C4PlantUmlExporterWithElementLinksTest.kt | 125 ++++++++++++------ .../generatr/site/model/MenuViewModelTest.kt | 5 +- .../site/model/SearchViewModelTest.kt | 26 ++++ ...wareSystemDependenciesPageViewModelTest.kt | 12 +- .../model/SoftwareSystemsPageViewModelTest.kt | 8 +- 12 files changed, 150 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 5462e31a..00384be1 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,8 @@ is generated from the example workspace in this repository. - Generates diagrams in SVG, PNG and PlantUML format, which can be viewed and downloaded from the generated site. - Easy browsing through the site by clicking on software system and container elements in the diagrams. Note that external software systems are excluded from the menu. A software system is considered external when it lives outside - the (deprecated) enterprise boundary or when groups are used and the software system is outside of any group. + the (deprecated) enterprise boundary or when it contains the tag that is defined in "generatr.site.excludedTag". + See (Customizing the generated website). - Start a development server which generates a site, serves it and updates the site automatically whenever a file that's part of the Structurizr workspace changes. - Include documentation (in Markdown or AsciiDoc format) in the generated site. Both workspace level documentation and software @@ -266,8 +267,8 @@ architecture model: | `generatr.search.language` | Indexing/stemming language for the search index. See [Lunr language support](https://github.com/olivernn/lunr-languages) | `en` | `nl` | | `generatr.markdown.flexmark.extensions` | Additional extensions to the markdown generator to add new markdown capabilities. [More Details](https://avisi-cloud.github.io/structurizr-site-generatr/main/extended-markdown-features/) | Tables | `Tables,Admonition` | | `generatr.svglink.target` | Specifies the link target for element links in the exported svg | `_top` | `_self` | -| `generatr.site.nestGroups` | Will show software systems in the left side navigator in collapsable groups | `false` | `true` | - +| `generatr.site.excludedTag` | Software systems containing this tag name will be considered external | | | +| `generatr.site.nestGroups` | Will show software systems in the left side navigator in collapsable ~~~~groups | `false` | `true` | See the included example for usage of some those properties in the [C4 architecture model example](https://github.com/avisi-cloud/structurizr-site-generatr/blob/main/docs/example/workspace.dsl#L163). diff --git a/docs/example/workspace.dsl b/docs/example/workspace.dsl index d09dbaaf..912cdefb 100644 --- a/docs/example/workspace.dsl +++ b/docs/example/workspace.dsl @@ -182,6 +182,7 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea // default behaviour, if no generatr.markdown.flexmark.extensions property is specified, is to load the Tables extension only "generatr.markdown.flexmark.extensions" "Abbreviation,Admonition,AnchorLink,Attributes,Autolink,Definition,Emoji,Footnotes,GfmTaskList,GitLab,MediaTags,Tables,TableOfContents,Typographic" + "generatr.site.excludedTag" "External System" "generatr.site.nestGroups" "false" } diff --git a/src/main/kotlin/nl/avisi/structurizr/site/generatr/StructurizrUtilities.kt b/src/main/kotlin/nl/avisi/structurizr/site/generatr/StructurizrUtilities.kt index 2fdf6ccf..efc94360 100644 --- a/src/main/kotlin/nl/avisi/structurizr/site/generatr/StructurizrUtilities.kt +++ b/src/main/kotlin/nl/avisi/structurizr/site/generatr/StructurizrUtilities.kt @@ -1,19 +1,17 @@ package nl.avisi.structurizr.site.generatr +import com.structurizr.Workspace import com.structurizr.model.Container import com.structurizr.model.Location import com.structurizr.model.Model import com.structurizr.model.SoftwareSystem import com.structurizr.view.ViewSet -val Model.includedSoftwareSystems: List - get() = if (softwareSystems.any { it.group != null }) - softwareSystems.filter { it.group != null } - else - softwareSystems.filter { it.location != Location.External } - -val Container.hasComponents - get() = this.components.isNotEmpty() +val Workspace.includedSoftwareSystems: List + get() = model.softwareSystems.filter { + val excludedTag = views.configuration.properties.getOrDefault("generatr.site.excludedTag", null) + it.location != Location.External && if (excludedTag != null) !it.tags.contains(excludedTag) else true + } val SoftwareSystem.hasContainers get() = this.containers.isNotEmpty() @@ -21,6 +19,9 @@ val SoftwareSystem.hasContainers val SoftwareSystem.includedProperties get() = this.properties.filterNot { (name, _) -> name == "structurizr.dsl.identifier" } +val Container.hasComponents + get() = this.components.isNotEmpty() + fun SoftwareSystem.hasDecisions() = documentation.decisions.isNotEmpty() fun SoftwareSystem.hasContainerDecisions() = containers.any { it.hasDecisions() } diff --git a/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/C4PlantUmlExporterWithElementLinks.kt b/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/C4PlantUmlExporterWithElementLinks.kt index 696af505..57848704 100644 --- a/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/C4PlantUmlExporterWithElementLinks.kt +++ b/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/C4PlantUmlExporterWithElementLinks.kt @@ -1,5 +1,6 @@ package nl.avisi.structurizr.site.generatr.site +import com.structurizr.Workspace import com.structurizr.export.Diagram import com.structurizr.export.IndentingWriter import com.structurizr.export.plantuml.C4PlantUMLExporter @@ -10,6 +11,7 @@ import com.structurizr.view.* import nl.avisi.structurizr.site.generatr.* class C4PlantUmlExporterWithElementLinks( + private val workspace: Workspace, private val url: String ) : C4PlantUMLExporter() { companion object { @@ -48,7 +50,7 @@ class C4PlantUmlExporterWithElementLinks( } private fun needsLinkToSoftwareSystem(element: Element?, view: ModelView?) = - element is SoftwareSystem && view != null && view.model.includedSoftwareSystems.contains(element) && element != view.softwareSystem + element is SoftwareSystem && view != null && workspace.includedSoftwareSystems.contains(element) && element != view.softwareSystem private fun getUrlToSoftwareSystem(element: Element?): String { val path = "/${element?.name?.normalize()}/context/".asUrlToDirectory(url) @@ -56,7 +58,7 @@ class C4PlantUmlExporterWithElementLinks( } private fun needsLinkToContainerViews(element: Element?, view: ModelView?) = - element is SoftwareSystem && view != null && view.model.includedSoftwareSystems.contains(element) && element == view.softwareSystem && element.hasContainers + element is SoftwareSystem && view != null && workspace.includedSoftwareSystems.contains(element) && element == view.softwareSystem && element.hasContainers private fun getUrlToContainerViews(element: Element?): String { val path = "/${element?.name?.normalize()}/container/".asUrlToDirectory(url) diff --git a/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/DiagramGenerator.kt b/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/DiagramGenerator.kt index 83e13e5e..71b2ec2d 100644 --- a/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/DiagramGenerator.kt +++ b/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/DiagramGenerator.kt @@ -9,6 +9,7 @@ import com.structurizr.view.View import net.sourceforge.plantuml.FileFormat import net.sourceforge.plantuml.FileFormatOption import net.sourceforge.plantuml.SourceStringReader +import nl.avisi.structurizr.site.generatr.includedSoftwareSystems import nl.avisi.structurizr.site.generatr.site.C4PlantUmlExporterWithElementLinks.Companion.export import java.io.ByteArrayOutputStream import java.io.File @@ -83,7 +84,7 @@ private fun saveAsPng(diagram: Diagram, pngDir: File) { } private fun generatePlantUMLDiagramWithElementLinks(workspace: Workspace, view: View, url: String): Diagram { - val plantUMLExporter = C4PlantUmlExporterWithElementLinks(url) + val plantUMLExporter = C4PlantUmlExporterWithElementLinks(workspace, url) if (workspace.views.configuration.properties.containsKey("generatr.svglink.target")) { plantUMLExporter.addSkinParam( diff --git a/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/SiteGenerator.kt b/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/SiteGenerator.kt index c97037f0..badf0261 100644 --- a/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/SiteGenerator.kt +++ b/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/SiteGenerator.kt @@ -131,7 +131,7 @@ private fun generateHtmlFiles(context: GeneratorContext, branchDir: File) { add { writeHtmlFile(branchDir, WorkspaceDecisionPageViewModel(context, it)) } } - context.workspace.model.includedSoftwareSystems.forEach { + context.workspace.includedSoftwareSystems.forEach { add { writeHtmlFile(branchDir, SoftwareSystemHomePageViewModel(context, it)) } add { writeHtmlFile(branchDir, SoftwareSystemContextPageViewModel(context, it)) } add { writeHtmlFile(branchDir, SoftwareSystemContainerPageViewModel(context, it)) } diff --git a/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/model/PageViewModel.kt b/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/model/PageViewModel.kt index b24fb262..f591720f 100644 --- a/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/model/PageViewModel.kt +++ b/src/main/kotlin/nl/avisi/structurizr/site/generatr/site/model/PageViewModel.kt @@ -20,7 +20,7 @@ abstract class PageViewModel(protected val generatorContext: GeneratorContext) { val flexmarkConfig by lazy { buildFlexmarkConfig(generatorContext) } val includeAdmonition = flexmarkConfig.selectedExtensionMap.containsKey("Admonition") val includeKatex = flexmarkConfig.selectedExtensionMap.containsKey("GitLab") - val includedSoftwareSystems = generatorContext.workspace.model.includedSoftwareSystems + val includedSoftwareSystems = generatorContext.workspace.includedSoftwareSystems val configuration = generatorContext.workspace.views.configuration.properties val includeTreeview = configuration.getOrDefault("generatr.site.nestGroups", "false").toBoolean() diff --git a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/C4PlantUmlExporterWithElementLinksTest.kt b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/C4PlantUmlExporterWithElementLinksTest.kt index b9918f1d..038aad2b 100644 --- a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/C4PlantUmlExporterWithElementLinksTest.kt +++ b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/C4PlantUmlExporterWithElementLinksTest.kt @@ -4,17 +4,16 @@ import assertk.assertThat import assertk.assertions.contains import assertk.assertions.isEqualTo import com.structurizr.Workspace -import com.structurizr.view.ContainerView -import com.structurizr.view.SystemContextView +import com.structurizr.model.Location import kotlin.test.Test class C4PlantUmlExporterWithElementLinksTest { @Test fun `adds skinparam to remove explicit size from generated svg`() { - val view = createWorkspaceWithOneSystem() + val workspace = createWorkspaceWithOneSystem() - val diagram = C4PlantUmlExporterWithElementLinks("/landscape/") - .export(view) + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/landscape/") + .export(workspace.views.systemContextViews.first()) assertThat(diagram.definition) .contains("skinparam svgDimensionStyle false") @@ -22,10 +21,10 @@ class C4PlantUmlExporterWithElementLinksTest { @Test fun `adds skinparam to preserve the aspect ratio of the generated svg`() { - val view = createWorkspaceWithOneSystem() + val workspace = createWorkspaceWithOneSystem() - val diagram = C4PlantUmlExporterWithElementLinks("/landscape/") - .export(view) + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/landscape/") + .export(workspace.views.systemContextViews.first()) assertThat(diagram.definition) .contains("skinparam preserveAspectRatio meet") @@ -33,10 +32,10 @@ class C4PlantUmlExporterWithElementLinksTest { @Test fun `renders diagram`() { - val view = createWorkspaceWithOneSystem() + val workspace = createWorkspaceWithOneSystem() - val diagram = C4PlantUmlExporterWithElementLinks("/landscape/") - .export(view) + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/landscape/") + .export(workspace.views.systemContextViews.first()) assertThat(diagram.definition.withoutHeaderAndFooter()).isEqualTo( """ @@ -47,10 +46,10 @@ class C4PlantUmlExporterWithElementLinksTest { @Test fun `renders System Diagram with link to container`() { - val view = createWorkspaceWithOneSystemWithContainers() + val workspace = createWorkspaceWithOneSystemWithContainers() - val diagram = C4PlantUmlExporterWithElementLinks("/container/") - .export(view) + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/container/") + .export(workspace.views.systemContextViews.first()) assertThat(diagram.definition.withoutHeaderAndFooter()).isEqualTo( """ @@ -61,10 +60,10 @@ class C4PlantUmlExporterWithElementLinksTest { @Test fun `renders System Diagram with link to other system and link to container`() { - val view = createWorkspaceWithTwoSystemWithContainers() + val workspace = createSystemContextViewForWorkspaceWithTwoSystemWithContainers() - val diagram = C4PlantUmlExporterWithElementLinks("/container/") - .export(view) + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/container/") + .export(workspace.views.systemContextViews.first()) assertThat(diagram.definition.withoutHeaderAndFooter()).isEqualTo( """ @@ -78,10 +77,10 @@ class C4PlantUmlExporterWithElementLinksTest { @Test fun `renders Container Diagram with link to component diagram`() { - val view = createWorkspaceWithOneSystemWithContainersAndComponents() + val workspace = createWorkspaceWithOneSystemWithContainersAndComponents() - val diagram = C4PlantUmlExporterWithElementLinks("/container/") - .export(view) + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/container/") + .export(workspace.views.containerViews.first()) assertThat(diagram.definition.withoutHeaderAndFooter()).isEqualTo( """ @@ -105,7 +104,7 @@ class C4PlantUmlExporterWithElementLinksTest { val view = workspace.views.createComponentView(container1, "Component2", "") .apply { addAllElements() } - val diagram = C4PlantUmlExporterWithElementLinks("/system-1/component/") + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/system-1/component/") .export(view) assertThat(diagram.definition.withoutHeaderAndFooter()).isEqualTo( @@ -125,10 +124,10 @@ class C4PlantUmlExporterWithElementLinksTest { @Test fun `link to other software system`() { - val view = createWorkspaceWithTwoSystems() + val workspace = createWorkspaceWithTwoSystems() - val diagram = C4PlantUmlExporterWithElementLinks("/landscape/") - .export(view) + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/landscape/") + .export(workspace.views.systemContextViews.first()) assertThat(diagram.definition.withoutHeaderAndFooter()).isEqualTo( """ @@ -141,12 +140,50 @@ class C4PlantUmlExporterWithElementLinksTest { } @Test - fun `link to other software system from two path segments deep`() { - val view = createWorkspaceWithTwoSystems() + fun `external software system (outside enterprise boundary)`() { + val workspace = createWorkspaceWithTwoSystems() + workspace.model.softwareSystems.single { it.name == "System 2" }.location = Location.External + + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/landscape/") + .export(workspace.views.systemContextViews.first()) + + assertThat(diagram.definition.withoutHeaderAndFooter()).isEqualTo( + """ + System(System1, "System 1", ${'$'}descr="", ${'$'}tags="", ${'$'}link="") + System_Ext(System2, "System 2", ${'$'}descr="", ${'$'}tags="", ${'$'}link="") - val diagram = C4PlantUmlExporterWithElementLinks("/system-1/context/") + Rel(System2, System1, "uses", ${'$'}techn="", ${'$'}tags="", ${'$'}link="") + """.trimIndent() + ) + } + + @Test + fun `external software system (declared external by tag)`() { + val workspace = createWorkspaceWithTwoSystems() + workspace.views.configuration.addProperty("generatr.site.excludedTag", "External System") + workspace.model.softwareSystems.single { it.name == "System 2" }.addTags("External System") + val view = workspace.views.systemContextViews.first() + + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/landscape/") .export(view) + assertThat(diagram.definition.withoutHeaderAndFooter()).isEqualTo( + """ + System(System1, "System 1", ${'$'}descr="", ${'$'}tags="", ${'$'}link="") + System(System2, "System 2", ${'$'}descr="", ${'$'}tags="", ${'$'}link="") + + Rel(System2, System1, "uses", ${'$'}techn="", ${'$'}tags="", ${'$'}link="") + """.trimIndent() + ) + } + + @Test + fun `link to other software system from two path segments deep`() { + val workspace = createWorkspaceWithTwoSystems() + + val diagram = C4PlantUmlExporterWithElementLinks(workspace, "/system-1/context/") + .export(workspace.views.systemContextViews.first()) + assertThat(diagram.definition.withoutHeaderAndFooter()).isEqualTo( """ System(System1, "System 1", ${'$'}descr="", ${'$'}tags="", ${'$'}link="") @@ -157,15 +194,19 @@ class C4PlantUmlExporterWithElementLinksTest { ) } - private fun createWorkspaceWithOneSystem(): SystemContextView { - val workspace = Workspace("workspace name", "") + private fun createWorkspaceWithOneSystem(): Workspace { + val workspace = Workspace("workspace name", "").apply { + views.configuration.addProperty("generatr.site.excludedTag", "External System") + } val system = workspace.model.addSoftwareSystem("System 1") - return workspace.views.createSystemContextView(system, "Context1", "") + workspace.views.createSystemContextView(system, "Context1", "") .apply { addAllElements() } + + return workspace } - private fun createWorkspaceWithOneSystemWithContainers(): SystemContextView? { + private fun createWorkspaceWithOneSystemWithContainers(): Workspace { val workspace = Workspace("workspace name", "") val system = workspace.model.addSoftwareSystem("System 1") system.addContainer("Container 1") @@ -174,11 +215,13 @@ class C4PlantUmlExporterWithElementLinksTest { workspace.views.createContainerView(system, "Container1", "") .apply { addAllElements() } - return workspace.views.createSystemContextView(system, "Context 1", "") + workspace.views.createSystemContextView(system, "Context 1", "") .apply { addAllElements() } + + return workspace } - private fun createWorkspaceWithTwoSystemWithContainers(): SystemContextView? { + private fun createSystemContextViewForWorkspaceWithTwoSystemWithContainers(): Workspace { val workspace = Workspace("workspace name", "") val system = workspace.model.addSoftwareSystem("System 1") workspace.model.addSoftwareSystem("System 2").apply { uses(system, "uses") } @@ -188,11 +231,13 @@ class C4PlantUmlExporterWithElementLinksTest { workspace.views.createContainerView(system, "Container1", "") .apply { addAllElements() } - return workspace.views.createSystemContextView(system, "Context 1", "") + workspace.views.createSystemContextView(system, "Context 1", "") .apply { addAllElements() } + + return workspace } - private fun createWorkspaceWithOneSystemWithContainersAndComponents(): ContainerView? { + private fun createWorkspaceWithOneSystemWithContainersAndComponents(): Workspace { val workspace = Workspace("workspace name", "") val system = workspace.model.addSoftwareSystem("System 1") val container = system.addContainer("Container 1") @@ -205,17 +250,21 @@ class C4PlantUmlExporterWithElementLinksTest { workspace.views.createComponentView(container, "Component1", "") - return workspace.views.createContainerView(system, "Container1", "") + workspace.views.createContainerView(system, "Container1", "") .apply { addAllElements() } + + return workspace } - private fun createWorkspaceWithTwoSystems(): SystemContextView { + private fun createWorkspaceWithTwoSystems(): Workspace { val workspace = Workspace("workspace name", "") val system = workspace.model.addSoftwareSystem("System 1") workspace.model.addSoftwareSystem("System 2").apply { uses(system, "uses") } - return workspace.views.createSystemContextView(system, "Context 1", "") + workspace.views.createSystemContextView(system, "Context 1", "") .apply { addAllElements() } + + return workspace } private fun String.withoutHeaderAndFooter() = this diff --git a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/MenuViewModelTest.kt b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/MenuViewModelTest.kt index e4821a99..99078c59 100644 --- a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/MenuViewModelTest.kt +++ b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/MenuViewModelTest.kt @@ -147,10 +147,11 @@ class MenuViewModelTest : ViewModelTest() { } @Test - fun `do not show menu entries for software systems with an external location (outside of any group when using groups)`() { + fun `do not show menu entries for software systems with an external location (declared external by tag)`() { val generatorContext = generatorContext(branches = listOf("main", "branch-2"), currentBranch = "main") + generatorContext.workspace.views.configuration.addProperty("generatr.site.excludedTag", "External System") generatorContext.workspace.model.addSoftwareSystem("System 1").apply { group = "Group 1" } - generatorContext.workspace.model.addSoftwareSystem("External system") + generatorContext.workspace.model.addSoftwareSystem("External system").apply { addTags("External System") } MenuViewModel(generatorContext, createPageViewModel(generatorContext, url = HomePageViewModel.url())) .let { diff --git a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SearchViewModelTest.kt b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SearchViewModelTest.kt index 440890cb..dda078c9 100644 --- a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SearchViewModelTest.kt +++ b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SearchViewModelTest.kt @@ -7,6 +7,7 @@ import assertk.assertions.isEmpty import assertk.assertions.isEqualTo import com.structurizr.documentation.Format import com.structurizr.documentation.Section +import com.structurizr.model.Location import org.junit.jupiter.api.Test class SearchViewModelTest : ViewModelTest() { @@ -61,6 +62,31 @@ class SearchViewModelTest : ViewModelTest() { .containsExactly("Context views") } + @Test + fun `indexes no external software system (outside enterprise boundary)`() { + val generatorContext = generatorContext() + generatorContext.workspace.apply { + model.addSoftwareSystem("Software system").apply { location = Location.External } + } + val viewModel = SearchViewModel(generatorContext) + + assertThat(viewModel.documents.map { it.type }) + .isEmpty() + } + + @Test + fun `indexes no external software system (declared external by tag)`() { + val generatorContext = generatorContext() + generatorContext.workspace.apply { + views.configuration.addProperty("generatr.site.excludedTag", "External System") + model.addSoftwareSystem("Software system").apply { addTags("External System") } + } + val viewModel = SearchViewModel(generatorContext) + + assertThat(viewModel.documents.map { it.type }) + .isEmpty() + } + @Test fun `indexes all software system information`() { val generatorContext = generatorContext() diff --git a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SoftwareSystemDependenciesPageViewModelTest.kt b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SoftwareSystemDependenciesPageViewModelTest.kt index 9641fbfc..030a021a 100644 --- a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SoftwareSystemDependenciesPageViewModelTest.kt +++ b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SoftwareSystemDependenciesPageViewModelTest.kt @@ -81,6 +81,7 @@ class SoftwareSystemDependenciesPageViewModelTest : ViewModelTest() { softwareSystem1.uses(backend2, "Uses from system 1 to container 2", "REST") val viewModel = SoftwareSystemDependenciesPageViewModel(generatorContext, softwareSystem1) + // Inbound Table assertThat(viewModel.dependenciesInboundTable.bodyRows.extractTitle()) .containsExactly("Software system 2") @@ -95,8 +96,8 @@ class SoftwareSystemDependenciesPageViewModelTest : ViewModelTest() { .addSoftwareSystem(Location.External, "External system", "") externalSystem.uses(softwareSystem1, "Uses", "REST") softwareSystem1.uses(externalSystem, "Uses", "REST") - val viewModel = SoftwareSystemDependenciesPageViewModel(generatorContext, softwareSystem1) + assertThat(viewModel.dependenciesInboundTable.bodyRows[0].columns[0]) .isEqualTo(TableViewModel.TextCellViewModel("External system (External)", isHeader = true, greyText = true)) assertThat(viewModel.dependenciesOutboundTable.bodyRows[0].columns[0]) @@ -104,13 +105,14 @@ class SoftwareSystemDependenciesPageViewModelTest : ViewModelTest() { } @Test - fun `dependencies from and to external systems (outside of any group when using groups)`() { - softwareSystem1.group = "Group 1" - val externalSystem = generatorContext.workspace.model.addSoftwareSystem("External system") + fun `dependencies from and to external systems (declared external by tag)`() { + generatorContext.workspace.views.configuration.addProperty("generatr.site.excludedTag", "External System") + val externalSystem = generatorContext.workspace.model.addSoftwareSystem("External system").apply { addTags("External System") } externalSystem.uses(softwareSystem1, "Uses", "REST") softwareSystem1.uses(externalSystem, "Uses", "REST") val viewModel = SoftwareSystemDependenciesPageViewModel(generatorContext, softwareSystem1) + assertThat(viewModel.dependenciesInboundTable.bodyRows[0].columns[0]) .isEqualTo(TableViewModel.TextCellViewModel("External system (External)", isHeader = true, greyText = true)) assertThat(viewModel.dependenciesOutboundTable.bodyRows[0].columns[0]) @@ -123,8 +125,8 @@ class SoftwareSystemDependenciesPageViewModelTest : ViewModelTest() { system.uses(softwareSystem1, "Uses", "REST") softwareSystem1.uses(softwareSystem2, "Uses REST", "REST") softwareSystem2.uses(softwareSystem1, "Uses SOAP", "SOAP") - val viewModel = SoftwareSystemDependenciesPageViewModel(generatorContext, softwareSystem1) + // Inbound Table assertThat(viewModel.dependenciesInboundTable.bodyRows.extractTitle()) .containsExactly("Software system 2", "Software system 3") diff --git a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SoftwareSystemsPageViewModelTest.kt b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SoftwareSystemsPageViewModelTest.kt index 50f75be3..a77402d1 100644 --- a/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SoftwareSystemsPageViewModelTest.kt +++ b/src/test/kotlin/nl/avisi/structurizr/site/generatr/site/model/SoftwareSystemsPageViewModelTest.kt @@ -79,10 +79,12 @@ class SoftwareSystemsPageViewModelTest : ViewModelTest() { } @Test - fun `external systems have grey text (outside of any group when using groups)`() { + fun `external systems have grey text (declared external by tag)`() { val generatorContext = generatorContext() - generatorContext.workspace.model.addSoftwareSystem("system 1", "System 1 description").apply { group = "Group 1" } - generatorContext.workspace.model.addSoftwareSystem("system 2", "System 2 description") + generatorContext.workspace.views.configuration.addProperty("generatr.site.excludedTag", "External System") + generatorContext.workspace.model.addSoftwareSystem("system 1", "System 1 description") + generatorContext.workspace.model.addSoftwareSystem("system 2", "System 2 description").apply { addTags("External System") } + val viewModel = SoftwareSystemsPageViewModel(generatorContext) assertThat(viewModel.softwareSystemsTable.bodyRows[1].columns[0])