diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ebfa13..a90e981 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,35 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/spec/v2.0.0.ht --- +## [2.47.3] — 2026-11-06 + +### 🐛 Fixed +- **Die JSON-LD-Ansicht in Tab 5 „Vorschau" fehlte bei jedem Datensatz.** Das HTML des Reiters + entstand bei der Feldregistrierung, bevor WordPress den bearbeiteten Datensatz kennt: + `get_the_ID()` lieferte dort `false`, und unter dem Hinweis „Die JSON-LD-Ansicht unten zeigt + das zuletzt gespeicherte Ergebnis" standen weder das JSON-LD noch der Button + „REST-Endpoint öffnen". Carbon Fields bekommt jetzt einen Callback, der erst beim Rendern + lĂ€uft. Neuer E2E-Test in `admin-workflow.spec.js`. +- **Lange Zeilen sprengen das Formular nicht mehr.** Das `
` von Carbon Fields hat ab + Werk `min-width: min-content`; die nun sichtbare JSON-LD-Ansicht schob den ganzen Kasten ĂŒber + den rechten Rand, statt im Code-Block zu scrollen (`assets/css/admin.css`, Block + `FORMULAR-DESIGN`). +- **Live-Vorschau mit Klartext:** Die Zusammenfassung zeigte beim Thema die EU-URI + (`http://publications.europa.eu/
/data-theme/ENVI`) statt „Umwelt" und die DateigrĂ¶ĂŸe in Bytes. + Sie nennt jetzt die Beschriftungen der Mehrfachauswahl und die GrĂ¶ĂŸe wie die Download-Card + („15 MB") und liest die Werte beim Wechsel des Reiters neu ein — die Mehrfachauswahl meldet + Änderungen nicht ĂŒber `input`/`change`. +- **Beispieldaten:** Zwei DatensĂ€tze („RadverkehrszĂ€hlstellen", „LadesĂ€ulen") trugen den + HVD-Code `c_b79e35eb` als Schlagwort; im Katalog erschien er als Filterwert und Badge. Jetzt + „MobilitĂ€t". `test-batch-import.php` lĂ€sst keine Vokabular-Codes als Schlagworte mehr durch. + +### 📝 Docs +- **Screenshots im README** (`docs/screenshots/`, nicht im Plugin-ZIP): Formular, Datenkatalog mit + Filtern und Detailansicht, Datensatzliste, Vorschau, QualitĂ€tsprĂŒfung und Batch-Import — + aufgenommen in einem deutschen WordPress mit den mitgelieferten Beispieldaten. + +--- + ## [2.47.2] — 2026-11-03 ### 🐛 Fixed diff --git a/CLAUDE.md b/CLAUDE.md index 8137a71..f46d7e7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -828,7 +828,7 @@ Update **both** locations: - MINOR: New features (backward-compatible) - PATCH: Bug fixes only -Current: **v2.47.2** +Current: **v2.47.3** --- @@ -981,6 +981,6 @@ Neue technische Festlegungen gehören dorthin, nicht in README oder CLAUDE.md. --- -**Zuletzt aktualisiert**: Version 2.47.2 (November 2026) +**Zuletzt aktualisiert**: Version 2.47.3 (November 2026) **Autor**: Open Data Wizard Team (nozilla) **License**: GPL-2.0-or-later diff --git a/README.md b/README.md index 310a8ad..70ff0e3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

Lizenz - Version + Version DCAT-AP 3.0 PHP >= 8.1 WordPress 6.4+ @@ -28,6 +28,19 @@ Open Data Wizard ermöglicht es Organisationen und Einzelpersonen, DatensĂ€tze direkt in WordPress zu beschreiben und als maschinenlesbare, standardkonforme Metadaten bereitzustellen — ohne technische Vorkenntnisse, ohne externe PlattformabhĂ€ngigkeit. + + + + + + + + + +
Datensatz bearbeiten: Formular mit fĂŒnf Reitern, Fragen in Alltagssprache und Pflichtfeld-SternchenDatenkatalog auf der Website mit Suche, Filtern und DatensĂ€tzen samt Thema, Format, GrĂ¶ĂŸe und Lizenz
Erfassen im WordPress-Backend: Fragen statt FachbegriffeVeröffentlichen auf der eigenen Website: der Datenkatalog
+ +Alle Screenshots zeigen die mitgelieferten Beispieldaten (frei erfunden: Musterstadt, Musterkreis, Musterland). + --- ## Das Problem @@ -82,6 +95,10 @@ Open Data Wizard implementiert **DCAT-AP 3.0** und erzeugt valide **JSON-LD**-Au ### 🗂 DatensĂ€tze verwalten Eigener Bereich im WordPress-Backend mit Übersicht, Filterung und Statusverwaltung (Entwurf / Veröffentlicht). +

+ Datensatzliste im Backend mit Spalten fĂŒr Lizenz, Thema, QualitĂ€t, Status, Änderungsdatum und Shortcode +

+ ### 😊 Benutzerfreundliche Formularsprache Das Wizard-Formular wurde vollstĂ€ndig ĂŒberarbeitet, um es auch ohne DCAT-AP-Kenntnisse intuitiv zu machen: - **Klare Fragen statt technischer Begriffe:** Statt „Herausgebende Organisation (dct:publisher)" fragt das Plugin: „Wer gibt diese Daten heraus?" @@ -98,6 +115,12 @@ FĂŒnf-Tab-Assistent mit praktischen Beispielen. Pflichtfelder sind mit einem rot 4. **Erweiterte Angaben** — Projektseite, Erstveröffentlichung, Aktualisierungsfrequenz, geografische und zeitliche Abdeckung, Kontaktinformationen, Verantwortlichkeiten (Urheber/pflegende Stelle, GovData-Contributor-ID), High-Value-Datensatz (HVD) Kategorie 5. **Vorschau** — generiertes JSON-LD live einsehen +Der Reiter **Vorschau** prĂŒft die Pflichtangaben noch wĂ€hrend des AusfĂŒllens und zeigt darunter das zuletzt gespeicherte JSON-LD — genau das, was Harvester abrufen. + +

+ Reiter Vorschau: Live-PrĂŒfung der Pflichtangaben, Zusammenfassung und das gespeicherte JSON-LD +

+ ### đŸ· Lizenz-Auswahl - Vordefinierte Auswahlliste mit ausgeschriebenen Lizenznamen (z. B. „CC BY 4.0 — Namensnennung") - Unter der Auswahl erscheint eine allgemeinverstĂ€ndliche ErklĂ€rung, was die gewĂ€hlte Lizenz erlaubt @@ -133,6 +156,10 @@ DatensĂ€tze → Batch-Import ``` Importiere mehrere DatensĂ€tze auf einmal aus CSV oder JSON Dateien. Der Import-Wizard zeigt eine Vorschau aller gĂŒltigen Zeilen, markiert Fehler, und lĂ€sst dich auswĂ€hlen, welche DatensĂ€tze importiert werden. Alle importierten DatensĂ€tze werden als **EntwĂŒrfe** erstellt — zur Bearbeitung vor Publishing bereit. +

+ Batch-Import: Vorschau mit drei gĂŒltigen DatensĂ€tzen und einer Fehlermeldung fĂŒr eine Zeile ohne Lizenz +

+ **UnterstĂŒtzte Formate:** - **CSV**: Spaltenköpfe = Feldnamen (siehe unten); Reihenfolge beliebig, nicht benötigte Spalten dĂŒrfen fehlen - **JSON**: Array von Objekten oder einzelnes Objekt mit gleichen Feldnamen @@ -225,6 +252,10 @@ Automatische Metadaten-QualitĂ€tsprĂŒfung nach der [EU-MQA-Methodik](https://dat Berechnung nach jedem Speichern. Die **Listenspalte** zeigt Prozent + Stufe; die **QualitĂ€ts-Meta-Box** ergĂ€nzt den MQA-Rohwert (z. B. „54 / 259 Punkte, von max. 405") als Detailzeile. +

+ QualitĂ€tsprĂŒfung (MQA): 100 Prozent, Stufe Ausgezeichnet, Punkte je Kriterium +

+ ### đŸ“„ Download-Card — Block oder Shortcode Zwei Wege zur selben Karte. **Empfohlen ist der Block:** @@ -262,6 +293,10 @@ Datenangebot. Ein Klick auf den Titel öffnet die vollstĂ€ndige Download-Card ** Seite** (`?odw_ds=`); „ZurĂŒck zum Katalog" fĂŒhrt auf die zuvor besuchte Listenseite zurĂŒck. Ab mehr EintrĂ€gen als `per_page` blĂ€ttert eine eigene Seitennavigation (`?odw_page=`). +

+ Detailansicht im Datenkatalog: Download-Card mit Format, GrĂ¶ĂŸe, Lizenz und aufgeklappten Metadaten +

+ | Attribut | Standard | Bedeutung | |---|---|---| | `per_page` | `20` | EintrĂ€ge pro Seite (1–50) | @@ -303,6 +338,10 @@ zurĂŒcksetzen" fĂŒhrt zur ungefilterten Liste. Fest eingestellte Themen (`theme` dem Weg in die Detailansicht und zurĂŒck erhalten. Ohne die beiden Attribute sieht ein Katalog genau so aus wie bisher. +

+ Datenkatalog mit Suche nach „Daten +

+ | Eintrag in `filters` | Feld im Formular | |---|---| | `theme`, `license`, `format` | Auswahlfeld Thema, Lizenz bzw. Format | diff --git a/assets/css/admin.css b/assets/css/admin.css index a052006..98e6f35 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -1297,7 +1297,7 @@ input.odw-cessda-input, Dieser Block hĂ€ngt an Klassennamen von Carbon Fields und ist damit die Stelle, die nach einem CF-Update zu prĂŒfen ist. Betroffen sind: - .cf-container__tab + .cf-container__tab, .cf-container__fields, .carbon-box fieldset .cf-field, .cf-field__head, .cf-field__label, .cf-field__body, .cf-field__help .cf-complex, .cf-complex__group, .cf-complex__group-head, @@ -1334,6 +1334,17 @@ input.odw-cessda-input, min-width: 0; } +/* Breiter Inhalt darf das Formular nicht aufspannen. Das
um den + * Container hat ab Werk `min-width: min-content`, die Flex-Kinder darunter + * `min-width: auto` — die lĂ€ngste Zeile der JSON-LD-Ansicht in Tab 5 schob + * so den ganzen Kasten ĂŒber den Rand hinaus, statt im Code-Block zu + * scrollen. */ +.postbox.carbon-box fieldset, +.cf-container__fields, +.cf-container__fields > .cf-field { + min-width: 0; +} + /* Der horizontale Abstand kommt jetzt vom Container. */ .cf-container__tab > .cf-field, .cf-container__tab > .odw-cessda-widget, diff --git a/assets/js/odw-admin-fields.js b/assets/js/odw-admin-fields.js index 01589b5..ac8ff93 100644 --- a/assets/js/odw-admin-fields.js +++ b/assets/js/odw-admin-fields.js @@ -778,11 +778,41 @@ return document.querySelector( '[name$="[_' + key + ']"]' ); } + // Wie ODW_Shortcode::format_bytes() — dieselbe Anzeige wie auf der Karte. + function formatBytes( bytes ) { + var units = [ [ 1073741824, 'GB' ], [ 1048576, 'MB' ], [ 1024, 'KB' ] ]; + for ( var i = 0; i < units.length; i++ ) { + if ( bytes >= units[ i ][ 0 ] ) { + return ( Math.round( bytes / units[ i ][ 0 ] * 10 ) / 10 ) + ' ' + units[ i ][ 1 ]; + } + } + return bytes + ' B'; + } + function fieldValue( key ) { var el = fieldInput( key ); if ( ! el ) { return ''; } + // Mehrfachauswahl (Thema, Engagementfeld 
): Das versteckte Feld trĂ€gt + // die URIs, durch „|" getrennt. Angezeigt werden die Beschriftungen, + // die Carbon Fields als Chips rendert — sonst stĂŒnde in der Vorschau + // „http://publications.europa.eu/
/data-theme/ENVI" statt „Umwelt". + var multi = el.closest( '.cf-multiselect' ); + if ( multi ) { + var labels = Array.prototype.map.call( + multi.querySelectorAll( '.cf-multiselect__multi-value__label' ), + function ( node ) { + return ( node.textContent || '' ).trim(); + } + ).filter( Boolean ); + if ( labels.length ) { + return labels.join( ', ' ); + } + } + if ( 'odw_byte_size' === key && /^\d+$/.test( ( el.value || '' ).trim() ) ) { + return formatBytes( parseInt( el.value, 10 ) ); + } if ( 'SELECT' === el.tagName && el.selectedIndex >= 0 ) { var opt = el.options[ el.selectedIndex ]; // Skip empty placeholder options ("— bitte wĂ€hlen —" style: empty value). @@ -862,6 +892,13 @@ // Update on any field change anywhere in the form (events bubble). document.addEventListener( 'input', refresh ); document.addEventListener( 'change', refresh ); + // Die Mehrfachauswahl setzt ihren Wert ohne input-/change-Ereignis. + // Beim Wechsel auf einen Reiter (also auch auf „Vorschau") neu lesen. + document.addEventListener( 'click', function ( event ) { + if ( event.target.closest && event.target.closest( '.cf-container__tabs-item' ) ) { + refresh(); + } + } ); refresh(); } diff --git a/docs/screenshots/batch-import.png b/docs/screenshots/batch-import.png new file mode 100644 index 0000000..21f585a Binary files /dev/null and b/docs/screenshots/batch-import.png differ diff --git a/docs/screenshots/datensatzliste.png b/docs/screenshots/datensatzliste.png new file mode 100644 index 0000000..3ea9de8 Binary files /dev/null and b/docs/screenshots/datensatzliste.png differ diff --git a/docs/screenshots/formular.png b/docs/screenshots/formular.png new file mode 100644 index 0000000..b1f721b Binary files /dev/null and b/docs/screenshots/formular.png differ diff --git a/docs/screenshots/katalog-detail.png b/docs/screenshots/katalog-detail.png new file mode 100644 index 0000000..103b5c3 Binary files /dev/null and b/docs/screenshots/katalog-detail.png differ diff --git a/docs/screenshots/katalog-filter.png b/docs/screenshots/katalog-filter.png new file mode 100644 index 0000000..01091ad Binary files /dev/null and b/docs/screenshots/katalog-filter.png differ diff --git a/docs/screenshots/katalog.png b/docs/screenshots/katalog.png new file mode 100644 index 0000000..7dc6f3b Binary files /dev/null and b/docs/screenshots/katalog.png differ diff --git a/docs/screenshots/qualitaet.png b/docs/screenshots/qualitaet.png new file mode 100644 index 0000000..1ed004a Binary files /dev/null and b/docs/screenshots/qualitaet.png differ diff --git a/docs/screenshots/vorschau.png b/docs/screenshots/vorschau.png new file mode 100644 index 0000000..87f1687 Binary files /dev/null and b/docs/screenshots/vorschau.png differ diff --git a/includes/class-fields.php b/includes/class-fields.php index 8901767..a0fc0c8 100644 --- a/includes/class-fields.php +++ b/includes/class-fields.php @@ -646,8 +646,13 @@ static function (): string { ->add_tab( __( '5 — Vorschau', 'open-data-wizard' ), array( + // Als Callback, nicht als fertiger String: Die Felder werden + // registriert, bevor WordPress den bearbeiteten Datensatz + // kennt — get_the_ID() liefert dort false, und die + // JSON-LD-Ansicht samt REST-Link fehlte bei jedem Datensatz. + // Carbon Fields ruft den Callback erst beim Rendern auf. Field::make( 'html', 'odw_preview_html' ) - ->set_html( self::get_preview_html() ), + ->set_html( static fn (): string => self::get_preview_html() ), Field::make( 'html', 'odw_datenatlas_publish' ) ->set_html( diff --git a/open-data-wizard.php b/open-data-wizard.php index 1e4c1cb..f771aca 100644 --- a/open-data-wizard.php +++ b/open-data-wizard.php @@ -3,7 +3,7 @@ * Plugin Name: Open Data Wizard * Plugin URI: https://github.com/daimpad/OpenDataWizard * Description: DCAT-AP 3.0 konforme Open Data Metadatenverwaltung fĂŒr WordPress. Bereitstellung als maschinenlesbarer JSON-LD-Endpoint fĂŒr offene Daten. - * Version: 2.47.2 + * Version: 2.47.3 * Requires at least: 6.4 * Requires PHP: 8.1 * Author: nozilla @@ -26,7 +26,7 @@ exit; } -define( 'ODW_VERSION', '2.47.2' ); +define( 'ODW_VERSION', '2.47.3' ); define( 'ODW_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'ODW_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); define( 'ODW_PLUGIN_FILE', __FILE__ ); diff --git a/package-lock.json b/package-lock.json index fbb70f9..94d8eb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-data-wizard", - "version": "2.47.2", + "version": "2.47.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "open-data-wizard", - "version": "2.47.2", + "version": "2.47.3", "license": "GPL-2.0-or-later", "devDependencies": { "@playwright/test": "^1.64.1", diff --git a/package.json b/package.json index 5703f9a..d5fe178 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-data-wizard", - "version": "2.47.2", + "version": "2.47.3", "description": "WordPress plugin for publishing open data as DCAT-AP 3.0 compliant metadata", "author": "Open Data Wizard Team", "license": "GPL-2.0-or-later", diff --git a/samples/import-example.csv b/samples/import-example.csv index 15d53ea..37c7e66 100644 --- a/samples/import-example.csv +++ b/samples/import-example.csv @@ -49,7 +49,7 @@ Haltestellen MobilitĂ€t","de","ZIP","application/zip","23068672","2024-01-02","2024-01-01","2024-12-31","WEEKLY","Musterland","state","https://www.vv-musterland.example/projekte/oepnv-fahrplan","Fahrplandaten-Team","opendata@vv-musterland.example","https://www.vv-musterland.example/kontakt","PUBLIC","STABLE","ja","c_b79e35eb","2024.52","https://gtfs.org/schedule/reference/" "RadverkehrszĂ€hlstellen: Stundenwerte 2021–2024","Stadt Musterstadt – MobilitĂ€tsamt","GezĂ€hlte Radfahrten je Stunde und Fahrtrichtung an den zwölf automatischen ZĂ€hlstellen im Stadtgebiet. AusfĂ€lle einzelner ZĂ€hlstellen sind gekennzeichnet.","https://www.musterstadt.example/opendata/radzaehlstellen","https://www.musterstadt.example/opendata/radzaehlstellen/radzaehlstellen.csv","dl-de-zero","","Nutzung ohne EinschrĂ€nkungen, auch ohne Nennung der Quelle.","TRAN","Radverkehr VerkehrszĂ€hlung -c_b79e35eb +MobilitĂ€t Messwerte","de","CSV","text/csv","18874368","2025-01-07","2021-01-01","2024-12-31","DAILY","Musterstadt","municipality","https://www.musterstadt.example/projekte/radzaehlstellen","MobilitĂ€tsamt, Verkehrsplanung","mobil@musterstadt.example","https://www.musterstadt.example/kontakt","PUBLIC","STABLE","ja","c_b79e35eb","1.4","" "LuftqualitĂ€t: Stundenmittel Stickstoffdioxid und Feinstaub 2018–2024","Stadt Musterstadt – Umweltamt","Stundenmittelwerte fĂŒr NO₂, PM10 und PM2,5 an den drei stĂ€dtischen Messstationen. Die Werte sind geprĂŒft; vorlĂ€ufige Werte des laufenden Jahres sind nicht enthalten.","https://www.musterstadt.example/opendata/luftqualitaet","https://www.musterstadt.example/opendata/luftqualitaet/luftqualitaet.json","dl-de-zero","","Nutzung ohne EinschrĂ€nkungen, auch ohne Nennung der Quelle.","ENVI","LuftqualitĂ€t Umwelt @@ -133,7 +133,7 @@ Klimaschutz Energie","de","CSV","text/csv","58368","2025-01-30","2018-01-01","2024-12-31","QUARTERLY","Musterstadt","municipality","https://www.stadtwerke-musterstadt.example/projekte/photovoltaik-staedtisch","Stadtwerke, Abteilung Energiedaten","opendata@stadtwerke-musterstadt.example","https://www.stadtwerke-musterstadt.example/kontakt","PUBLIC","STABLE","nein","","1.2","" "LadesĂ€ulen fĂŒr Elektrofahrzeuge 2024","Stadtwerke Musterstadt GmbH","Öffentlich zugĂ€ngliche Ladepunkte im Stadtgebiet mit Betreiber, Ladeleistung, Steckertyp und Standort, Stand Ende 2024.","https://www.stadtwerke-musterstadt.example/opendata/ladesaeulen","https://www.stadtwerke-musterstadt.example/opendata/ladesaeulen/ladesaeulen.geojson","dl-de-zero","","Nutzung ohne EinschrĂ€nkungen, auch ohne Nennung der Quelle.","ENER,TRAN","ElektromobilitĂ€t Ladeinfrastruktur -c_b79e35eb +MobilitĂ€t Geodaten","de","GeoJSON","application/geo+json","131072","2025-01-08","2024-01-01","2024-12-31","MONTHLY","Musterstadt","municipality","https://www.stadtwerke-musterstadt.example/projekte/ladesaeulen","Stadtwerke, Abteilung Energiedaten","opendata@stadtwerke-musterstadt.example","https://www.stadtwerke-musterstadt.example/kontakt","PUBLIC","STABLE","ja","c_b79e35eb","2024.12","https://www.rfc-editor.org/rfc/rfc7946" "Polizeiliche Kriminalstatistik Musterkreis 2015–2024","Polizeidirektion Musterkreis","Erfasste Straftaten, AufklĂ€rungsquoten und TatverdĂ€chtige nach Deliktgruppe und Gemeinde. Die Zahlen folgen den Richtlinien der Polizeilichen Kriminalstatistik.","https://www.polizei-musterkreis.example/opendata/kriminalstatistik","https://www.polizei-musterkreis.example/opendata/kriminalstatistik/kriminalstatistik.xlsx","dl-de-by","Datenquelle: Polizeidirektion Musterkreis, 2025, Lizenz Datenlizenz Deutschland – Namensnennung 2.0","Nutzung fĂŒr jeden Zweck erlaubt, auch kommerziell; die Quelle ist zu nennen.","JUST","KriminalitĂ€t Sicherheit diff --git a/samples/import-example.json b/samples/import-example.json index bbce9de..11f12d8 100644 --- a/samples/import-example.json +++ b/samples/import-example.json @@ -393,7 +393,7 @@ "attribution": "", "rights": "Nutzung ohne EinschrĂ€nkungen, auch ohne Nennung der Quelle.", "theme": "TRAN", - "keywords": "Radverkehr\nVerkehrszĂ€hlung\nc_b79e35eb\nMesswerte", + "keywords": "Radverkehr\nVerkehrszĂ€hlung\nMobilitĂ€t\nMesswerte", "language": "de", "format": "CSV", "media_type": "text/csv", @@ -1065,7 +1065,7 @@ "attribution": "", "rights": "Nutzung ohne EinschrĂ€nkungen, auch ohne Nennung der Quelle.", "theme": "ENER,TRAN", - "keywords": "ElektromobilitĂ€t\nLadeinfrastruktur\nc_b79e35eb\nGeodaten", + "keywords": "ElektromobilitĂ€t\nLadeinfrastruktur\nMobilitĂ€t\nGeodaten", "language": "de", "format": "GeoJSON", "media_type": "application/geo+json", diff --git a/tests/e2e/admin-workflow.spec.js b/tests/e2e/admin-workflow.spec.js index 6bd793f..24c5167 100644 --- a/tests/e2e/admin-workflow.spec.js +++ b/tests/e2e/admin-workflow.spec.js @@ -235,6 +235,27 @@ test.describe('Formular', () => { ); }); + // Bis 2.47.2 entstand das HTML dieses Reiters schon bei der Feldregistrierung, + // bevor WordPress den Datensatz kannte: JSON-LD und REST-Link fehlten immer, + // nur der Hinweis „Die JSON-LD-Ansicht unten 
" stand da. + test('die Vorschau zeigt das gespeicherte JSON-LD und den REST-Link', async ({ page }) => { + await page.goto(LIST_URL); + await page.locator('#the-list a.row-title', { hasText: 'E2E: Schulstandorte' }).click(); + + await page.locator('.cf-container__tabs-item button', { hasText: 'Vorschau' }).click(); + + const code = page.locator('#odw-jsonld-preview pre.odw-jsonld-code'); + await expect(code).toBeVisible(); + await expect(code).toContainText('"@type": "dcat:Dataset"'); + await expect(code).toContainText('E2E: Schulstandorte'); + await expect(page.getByRole('link', { name: 'REST-Endpoint öffnen' })).toHaveAttribute('href', /datenatlas\/v1\/datasets\/\d+/); + + // Die Zusammenfassung nennt das Thema beim Namen, nicht als EU-URI. + const card = page.locator('[data-odw-live-card]'); + await expect(card).toContainText('Bildung'); + await expect(card).not.toContainText('publications.europa.eu'); + }); + test('wechselt auf den zweiten Reiter', async ({ page }) => { await page.goto('/wp-admin/post-new.php?post_type=odw_dataset'); diff --git a/tests/test-batch-import.php b/tests/test-batch-import.php index 3839dc1..9768d5b 100644 --- a/tests/test-batch-import.php +++ b/tests/test-batch-import.php @@ -629,6 +629,13 @@ public function test_sample_files_match_and_cover_every_column(): void { } $this->assertSame( 'ja' === $record['hvd'], '' !== $record['hvd_category'], sprintf( 'Datensatz %d: HVD ohne Kategorie oder umgekehrt.', $index + 1 ) ); $this->assertLessThanOrEqual( $record['temporal_end'], $record['temporal_start'] ); + + // Schlagworte sind Wörter, keine Vokabular-Codes. Zwei DatensĂ€tze + // trugen den HVD-Code „c_b79e35eb" als Schlagwort — im Katalog stand + // er dann als Filterwert und als Badge. + foreach ( preg_split( '/\R/', (string) $record['keywords'] ) as $keyword ) { + $this->assertDoesNotMatchRegularExpression( '/^c_[0-9a-f]{8}$/', trim( $keyword ), sprintf( 'Datensatz %d: Vokabular-Code als Schlagwort.', $index + 1 ) ); + } } }