Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions openspec/specs/org-archimate-export/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Organizations using the softwarecatalog map their applications to GEMMA referent
## Requirements

### Requirement: Export MUST produce valid ArchiMate XML with organization applications
@e2e exclude pure backend/XML-generation contract - covered by PHPUnit/Newman
The organization export MUST generate a valid AMEFF XML file that includes all base GEMMA objects plus synthesized application elements, specialization relationships, enriched view copies, and organization folder structure.

#### Scenario: Organization with mapped applications exports successfully
Expand Down Expand Up @@ -65,6 +66,7 @@ The organization export MUST generate a valid AMEFF XML file that includes all b
- AND the response MUST be streamed (not buffered entirely in memory) for files over 10MB

### Requirement: Application elements MUST be ApplicationComponent type with Bron property
@e2e exclude pure backend/XML-generation contract - covered by PHPUnit/Newman
Each organization application MUST be exported as an ArchiMate `<element>` with `xsi:type="ApplicationComponent"`, a unique identifier, and a `Bron=Softwarecatalogus` property.

#### Scenario: Application element has correct structure
Expand Down Expand Up @@ -93,6 +95,7 @@ Each organization application MUST be exported as an ArchiMate `<element>` with
- AND the output MUST contain `R&amp;D Tool &lt;v2&gt;`

### Requirement: SpecializationRelationship MUST link applications to referentiecomponenten
@e2e exclude pure backend/XML-generation contract - covered by PHPUnit/Newman
Each application-to-referentiecomponent mapping MUST produce a `<relationship>` of type `SpecializationRelationship` in the export.

#### Scenario: Application mapped to one referentiecomponent
Expand Down Expand Up @@ -121,6 +124,7 @@ Each application-to-referentiecomponent mapping MUST produce a `<relationship>`
- AND the `target` attribute MUST reference an existing `<element>` identifier in the same file

### Requirement: Views MUST be copied with applications plotted inside referentiecomponenten
@e2e exclude pure backend/XML-generation contract - covered by PHPUnit/Newman
The export MUST create copies of qualifying GEMMA views and inject application nodes as children of their mapped referentiecomponent nodes.

#### Scenario: View with applications plotted on referentiecomponenten
Expand Down Expand Up @@ -158,6 +162,7 @@ The export MUST create copies of qualifying GEMMA views and inject application n
- AND both views MUST coexist in the XML

### Requirement: View copies MUST use Titel view SWC property for naming
@e2e exclude pure backend/XML-generation contract - covered by PHPUnit/Newman
Copied views MUST be named using the `Titel view SWC` property from the original view combined with the organization name.

#### Scenario: View has Titel view SWC property
Expand All @@ -180,6 +185,7 @@ Copied views MUST be named using the `Titel view SWC` property from the original
- AND the name MUST NOT be truncated

### Requirement: SWC objects MUST be organized in typed folders
@e2e exclude pure backend/XML-generation contract - covered by PHPUnit/Newman
All SWC-added elements MUST be placed in organisation folders within the `<organizations>` section, separated by relationship type.

#### Scenario: Organisation folders created with typed subfolders
Expand Down Expand Up @@ -213,6 +219,7 @@ All SWC-added elements MUST be placed in organisation folders within the `<organ
- AND no orphaned references MUST exist

### Requirement: File and model MUST follow naming convention
@e2e exclude pure backend/XML-generation contract - covered by PHPUnit/Newman
The export file name and ArchiMate model name MUST include the organization name and export date.

#### Scenario: File name includes date and organization
Expand All @@ -233,6 +240,7 @@ The export file name and ArchiMate model name MUST include the organization name
- AND the model `<name>` MUST preserve the original name: "Softwarecatalogus Gemeente 's-Hertogenbosch"

### Requirement: API endpoint MUST accept organization UUID and return XML download
@e2e exclude pure backend/API contract - covered by PHPUnit/Newman
The export MUST be triggered via `GET /api/archimate/export/organization/{organizationUuid}` with the organization UUID as a path parameter and optional boolean query parameters.

#### Scenario: Valid organization UUID provided
Expand Down Expand Up @@ -268,6 +276,7 @@ The export MUST be triggered via `GET /api/archimate/export/organization/{organi
- AND the response MUST indicate insufficient permissions

### Requirement: Bron property definition MUST be added to the model
@e2e exclude pure backend/XML-generation contract - covered by PHPUnit/Newman
The export MUST include a `<propertyDefinition>` for "Bron" so that the `Bron=Softwarecatalogus` property on SWC objects references a valid definition.

#### Scenario: Bron property definition does not already exist
Expand All @@ -287,6 +296,7 @@ The export MUST include a `<propertyDefinition>` for "Bron" so that the `Bron=So
- THEN each `<property>` element's `propertyDefinitionRef` MUST point to a valid `<propertyDefinition>` identifier

### Requirement: Connection elements MUST be created for plotted applications
@e2e exclude pure backend/XML-generation contract - covered by PHPUnit/Newman
Each application node plotted inside a referentiecomponent MUST have a corresponding `<connection>` element in the view linking it via the specialization relationship.

#### Scenario: Connection links application node to referentiecomponent node
Expand All @@ -310,6 +320,7 @@ Each application node plotted inside a referentiecomponent MUST have a correspon
- AND a warning MUST be logged about the missing relationship

### Requirement: Export MUST include deelname data when deelnames parameter is enabled
@e2e exclude pure backend contract - covered by PHPUnit/Newman
When the `deelnames` query parameter is `true`, the export MUST query gebruik objects where the current organisation's UUID appears in the `deelnemers` field (with RBAC disabled) and include those applications in the output.

#### Scenario: Organisation has deelname gebruik
Expand Down Expand Up @@ -340,6 +351,7 @@ When the `deelnames` query parameter is `true`, the export MUST query gebruik ob
- AND both MUST be distinct elements in the XML

### Requirement: Deelname query MUST use RBAC-disabled ObjectService search
@e2e exclude pure backend contract - covered by PHPUnit/Newman
Deelname gebruik objects are owned by other organisations. The query MUST bypass RBAC to find records where the current organisation appears in the `deelnemers` array.

#### Scenario: Deelname query filters on deelnemers field
Expand All @@ -356,6 +368,7 @@ Deelname gebruik objects are owned by other organisations. The query MUST bypass
- AND no error MUST be logged for empty results

### Requirement: Export MUST support query parameters for toggling data layers
@e2e exclude pure backend/API contract - covered by PHPUnit/Newman
The GET endpoint MUST accept boolean query parameters that control which data is included in the export.

#### Scenario: All parameters enabled
Expand Down Expand Up @@ -385,6 +398,7 @@ The GET endpoint MUST accept boolean query parameters that control which data is
- AND the API MUST treat `1`, `yes`, `true`, `TRUE` as truthy values

### Requirement: Frontend MUST provide organization export with data layer toggles
@e2e exclude SPA does not mount: webpack runtime chunk not loaded in templates (GH issue #322)
The ArchiMate settings section MUST include checkboxes for selecting which data layers to include, and trigger the export via the GET endpoint.

#### Scenario: User triggers organization export with toggles
Expand Down
28 changes: 28 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: EUPL-1.2
// SPDX-FileCopyrightText: 2026 Conduction B.V.

import { defineConfig, devices } from '@playwright/test'

/**
* Playwright configuration for softwarecatalog e2e tests.
* Base URL: http://localhost:8080 (Nextcloud dev container)
*/
export default defineConfig({
testDir: './tests/e2e',
fullyParallel: false,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 1 : 0,
workers: 1,
reporter: 'list',
use: {
baseURL: process.env.BASE_URL ?? 'http://localhost:8080',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
})
78 changes: 78 additions & 0 deletions tests/e2e/org-archimate-export.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: EUPL-1.2
// SPDX-FileCopyrightText: 2026 Conduction B.V.
/**
* E2e coverage file for openspec/specs/org-archimate-export/spec.md
*
* Coverage status
* ---------------
* All 49 backend/XML-generation scenarios (Requirements 1–13) are excluded
* from Playwright coverage: they are pure server-side contracts verified by
* PHPUnit and Newman/Postman tests.
*
* The 4 frontend scenarios (Requirement 14: "Frontend MUST provide organization
* export with data layer toggles") are excluded because the softwarecatalog SPA
* does not mount: the webpack runtime chunk is not loaded by the PHP templates,
* leaving <div id="softwarecatalog"> and <div id="settings"> permanently empty.
* See GH issue #322 for the fix.
*
* Excluded scenarios (backend – 49 total):
* @e2e org-archimate-export::organization-with-mapped-applications-exports-successfully
* @e2e org-archimate-export::organization-with-no-mapped-applications
* @e2e org-archimate-export::export-preserves-all-base-gemma-data
* @e2e org-archimate-export::export-xml-is-well-formed-and-schema-valid
* @e2e org-archimate-export::large-organization-export-completes-within-timeout
* @e2e org-archimate-export::application-element-has-correct-structure
* @e2e org-archimate-export::application-element-has-unique-swc-identifier
* @e2e org-archimate-export::application-element-identifier-is-deterministic
* @e2e org-archimate-export::application-element-name-handles-special-xml-characters
* @e2e org-archimate-export::application-mapped-to-one-referentiecomponent
* @e2e org-archimate-export::application-mapped-to-multiple-referentiecomponenten
* @e2e org-archimate-export::relationship-identifiers-are-deterministic
* @e2e org-archimate-export::relationship-source-and-target-reference-valid-elements
* @e2e org-archimate-export::view-with-applications-plotted-on-referentiecomponenten
* @e2e org-archimate-export::multiple-applications-stacked-inside-one-referentiecomponent
* @e2e org-archimate-export::application-appears-in-multiple-referentiecomponenten-across-views
* @e2e org-archimate-export::view-without-any-matching-referentiecomponenten
* @e2e org-archimate-export::original-gemma-views-are-preserved-unchanged
* @e2e org-archimate-export::view-has-titel-view-swc-property
* @e2e org-archimate-export::view-without-titel-view-swc-property
* @e2e org-archimate-export::view-name-handles-long-organization-names
* @e2e org-archimate-export::organisation-folders-created-with-typed-subfolders
* @e2e org-archimate-export::empty-folders-are-omitted
* @e2e org-archimate-export::only-deelnames-enabled-produces-only-deelnames-folder
* @e2e org-archimate-export::folder-item-references-are-valid
* @e2e org-archimate-export::file-name-includes-date-and-organization
* @e2e org-archimate-export::model-name-includes-organization
* @e2e org-archimate-export::file-name-sanitizes-special-characters-in-organization-name
* @e2e org-archimate-export::valid-organization-uuid-provided
* @e2e org-archimate-export::valid-organization-uuid-with-query-parameters
* @e2e org-archimate-export::non-existent-organization-uuid
* @e2e org-archimate-export::unauthenticated-request-is-rejected
* @e2e org-archimate-export::non-admin-user-is-rejected
* @e2e org-archimate-export::bron-property-definition-does-not-already-exist
* @e2e org-archimate-export::bron-property-definition-already-exists
* @e2e org-archimate-export::bron-property-references-are-valid
* @e2e org-archimate-export::connection-links-application-node-to-referentiecomponent-node
* @e2e org-archimate-export::connection-identifiers-are-unique
* @e2e org-archimate-export::connection-without-matching-relationship-is-not-created
* @e2e org-archimate-export::organisation-has-deelname-gebruik
* @e2e org-archimate-export::organisation-has-no-deelname-gebruik
* @e2e org-archimate-export::deelnames-parameter-is-not-set
* @e2e org-archimate-export::deelname-applications-have-distinct-identifiers
* @e2e org-archimate-export::deelname-query-filters-on-deelnemers-field
* @e2e org-archimate-export::deelname-query-handles-no-results-gracefully
* @e2e org-archimate-export::all-parameters-enabled
* @e2e org-archimate-export::no-parameters-provided-default-behavior
* @e2e org-archimate-export::only-deelnames-enabled
* @e2e org-archimate-export::boolean-parameters-accept-various-truthy-values
*
* Excluded scenarios (SPA not mounted – 4 total, GH issue #322):
* @e2e org-archimate-export::user-triggers-organization-export-with-toggles
* @e2e org-archimate-export::no-organization-selected
* @e2e org-archimate-export::default-checkbox-state
* @e2e org-archimate-export::export-button-shows-loading-state-during-download
*/

// No runnable tests: all scenarios are excluded from Playwright coverage.
// See spec annotations and comments above for the authoritative reason per scenario.
export {}