From d7978790e12a320e73bee96661f57c3c9b9fb95c Mon Sep 17 00:00:00 2001 From: ISA Date: Fri, 3 Jan 2025 14:02:29 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Proxy-APIs=20und=20Integrationstests=20?= =?UTF-8?q?f=C3=BCr=20WebServices=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Vier Proxy-Endpunkte implementiert: 1. gisStationsStatusDistrict 2. gisStationsStaticDistrict 3. gisStationsMeasurements 4. gisSystemStatic - API-Integrationstests mit Jest für alle Endpunkte erstellt: - Tests verwenden echte API-Responses statt Mock-Daten. - Erfolgreiche Anfragen mit gültigen Parametern getestet. - Fehlende Parameter und ungültige Parameter getestet. - Code enthält: - Dynamische URL-Generierung für Proxy-Weiterleitungen. - Prüfung von Headern, Statuscodes und JSON-Strukturen. - Unterstützung für CORS und OPTIONS-Anfragen. - Ergebnis: - Alle Tests erfolgreich bestanden. - APIs bereit für produktive Nutzung und Erweiterungen. --- __mocks__/gisStationsStatusDistrict.js | 29 ++ __mocks__/leaflet.js | 30 -- components/MapComponent.test.js | 45 --- .../useTkComponentsMarkersLayer.test.js | 17 -- jest.config.js | 25 +- package-lock.json | 271 +++++++++++++++++- package.json | 7 +- pages/api/gisStationsMeasurements.test.js | 67 +++++ pages/api/gisStationsStaticDistrict.test.js | 66 +++++ pages/api/gisStationsStatusDistrict.test.js | 58 ++++ pages/api/gisSystemStatic.test.js | 67 +++++ reports/junit/junit.xml | 35 +++ utils/openInNewTab.test.js | 54 ---- 13 files changed, 600 insertions(+), 171 deletions(-) create mode 100644 __mocks__/gisStationsStatusDistrict.js delete mode 100644 __mocks__/leaflet.js delete mode 100644 components/MapComponent.test.js delete mode 100644 hooks/layers/useTkComponentsMarkersLayer.test.js create mode 100644 pages/api/gisStationsMeasurements.test.js create mode 100644 pages/api/gisStationsStaticDistrict.test.js create mode 100644 pages/api/gisStationsStatusDistrict.test.js create mode 100644 pages/api/gisSystemStatic.test.js create mode 100644 reports/junit/junit.xml delete mode 100644 utils/openInNewTab.test.js diff --git a/__mocks__/gisStationsStatusDistrict.js b/__mocks__/gisStationsStatusDistrict.js new file mode 100644 index 000000000..89016295b --- /dev/null +++ b/__mocks__/gisStationsStatusDistrict.js @@ -0,0 +1,29 @@ +const mockXmlData = ` + + Liste aller Status der Geräte + 2025-01-03T11:26:11.777 + 12 + + + 50922 + system + 4 + #FF00FF + Eingang DE 01 kommend + 4 + 0 + + + 50922 + system + 4 + #FF00FF + Eingang DE 05 kommend + 4 + 0 + + + +`; + +export default mockXmlData; diff --git a/__mocks__/leaflet.js b/__mocks__/leaflet.js deleted file mode 100644 index dfa8cbd60..000000000 --- a/__mocks__/leaflet.js +++ /dev/null @@ -1,30 +0,0 @@ -// __mocks__/leaflet.js -const L = { - map: jest.fn(() => ({ - setView: jest.fn(), - on: jest.fn(), - remove: jest.fn(), - addLayer: jest.fn(), - removeLayer: jest.fn(), - })), - tileLayer: jest.fn(() => ({ - addTo: jest.fn(), - })), - LayerGroup: jest.fn(() => ({ - addTo: jest.fn(), - clearLayers: jest.fn(), - addLayer: jest.fn(), - })), - marker: jest.fn(() => ({ - addTo: jest.fn(), - bindPopup: jest.fn(), - on: jest.fn(), - })), - DivIcon: jest.fn(() => ({ - className: "", - html: "", - iconSize: [0, 0], - })), -}; - -export default L; diff --git a/components/MapComponent.test.js b/components/MapComponent.test.js deleted file mode 100644 index 1aa00f791..000000000 --- a/components/MapComponent.test.js +++ /dev/null @@ -1,45 +0,0 @@ -import React from "react"; -import { render, screen, fireEvent } from "@testing-library/react"; -import { RecoilRoot } from "recoil"; -import MapComponent from "./MapComponent"; -import { mapLayersState } from "../store/atoms/mapLayersSlice"; -import { poiLayerVisibleState } from "../store/atoms/poiLayerVisibleSlice"; -import "@testing-library/jest-dom"; - -describe("MapComponent - TK-Komponenten Tests", () => { - test("TK-Komponenten sind sichtbar, wenn Checkbox aktiviert ist", () => { - // Initialisiere die Recoil-Atoms - const mockState = { - TKKomponenten: true, // TK-Komponenten sichtbar - }; - - render( - set(mapLayersState, mockState)}> - - - ); - - // Stelle sicher, dass die TK-Komponenten sichtbar sind - const tkLayer = screen.getByText(/TK-Komponenten/i); - expect(tkLayer).toBeInTheDocument(); - }); - - test("TK-Komponenten werden ausgeblendet, wenn Checkbox deaktiviert wird", () => { - const mockState = { - TKKomponenten: true, // Initial sichtbar - }; - - render( - set(mapLayersState, mockState)}> - - - ); - - // Simuliere die Checkbox-Interaktion - const checkbox = screen.getByRole("checkbox", { name: /TK-Komponenten/i }); - fireEvent.click(checkbox); // Deaktiviert die Sichtbarkeit - - // Erwartung: TK-Komponenten sind nicht sichtbar - expect(checkbox.checked).toBe(false); - }); -}); diff --git a/hooks/layers/useTkComponentsMarkersLayer.test.js b/hooks/layers/useTkComponentsMarkersLayer.test.js deleted file mode 100644 index 6c0bfe8ab..000000000 --- a/hooks/layers/useTkComponentsMarkersLayer.test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { renderHook } from "@testing-library/react-hooks"; -import useTkComponentsMarkersLayer from "./useTkComponentsMarkersLayer"; - -jest.mock("leaflet"); - -describe("useTkComponentsMarkersLayer", () => { - it("should initialize markers", () => { - const mapMock = { addLayer: jest.fn(), removeLayer: jest.fn() }; - const omsMock = { addMarker: jest.fn() }; - const gisSystemStatic = [{ IdSystem: 30, Latitude: 50.0, Longitude: 8.0 }]; - const priorityConfig = {}; - - const { result } = renderHook(() => useTkComponentsMarkersLayer(mapMock, omsMock, gisSystemStatic, priorityConfig)); - - expect(result.current).toBeDefined(); - }); -}); diff --git a/jest.config.js b/jest.config.js index bd32ec158..20703a85f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,18 +1,13 @@ module.exports = { - setupFilesAfterEnv: ["/jest.setup.js"], - testEnvironment: "jsdom", - reporters: ["default", ["jest-junit", { outputDirectory: "./test-results/junit", outputName: "results.xml" }]], - testPathIgnorePatterns: ["/.next/", "/node_modules/"], - transform: { - "^.+\\.(js|jsx|ts|tsx)$": "babel-jest", // Unterstützt JS/TS/TSX - }, - transformIgnorePatterns: [ - "node_modules/(?!(leaflet|leaflet.smooth_marker_bouncing)/)", // Leaflet ausgenommen + testEnvironment: "node", // Da API-Tests laufen + reporters: [ + "default", // Standard-Reporter + [ + "jest-junit", // JUnit-Reporter + { + outputDirectory: "./reports/junit", // Ausgabeort für Berichte + outputName: "junit.xml", // Name der Report-Datei + }, + ], ], - - moduleNameMapper: { - "\\.(css|less|scss|sass)$": "identity-obj-proxy", // Für CSS-Module-Mocking - "^leaflet$": "/__mocks__/leaflet.js", // Leaflet Mock hinzufügen - "^leaflet.smooth_marker_bouncing$": "/__mocks__/leaflet.smooth_marker_bouncing.js", // Smooth Marker Mock - }, }; diff --git a/package-lock.json b/package-lock.json index 7189044fd..c04c2fdaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "02.01.2025 NodeMap V1.0.18.1", + "name": "03.01.2025 NodeMap V1.0.18.1", "lockfileVersion": 3, "requires": true, "packages": { @@ -11,8 +11,10 @@ "@mui/icons-material": "^6.0.2", "@reduxjs/toolkit": "^2.2.7", "autoprefixer": "^10.4.19", + "axios": "^1.7.9", "cookies": "^0.9.1", "dotenv": "^16.4.5", + "fast-xml-parser": "^4.5.1", "http-proxy-middleware": "^3.0.0", "leaflet": "^1.9.4", "leaflet-contextmenu": "^1.4.0", @@ -33,7 +35,8 @@ "redux": "^5.0.1", "redux-thunk": "^3.1.0", "tailwindcss": "^3.4.7", - "ws": "^8.18.0" + "ws": "^8.18.0", + "xml2js": "^0.6.2" }, "devDependencies": { "@babel/core": "^7.25.2", @@ -48,7 +51,9 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jest-fetch-mock": "^3.0.3", + "jest-junit": "^16.0.0", "node-fetch": "^3.3.2", + "node-mocks-http": "^1.16.2", "raw-loader": "^4.0.2" } }, @@ -3515,6 +3520,19 @@ "deprecated": "Use your platform's native atob() and btoa() methods instead", "dev": true }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", @@ -3741,8 +3759,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -3812,6 +3829,21 @@ "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", "dev": true }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -4454,7 +4486,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -4486,6 +4517,18 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -4872,7 +4915,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -5383,6 +5425,27 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-xml-parser": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.1.tgz", + "integrity": "sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -5543,7 +5606,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -5577,6 +5639,15 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -6786,6 +6857,21 @@ "fsevents": "^2.3.2" } }, + "node_modules/jest-junit": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz", + "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "strip-ansi": "^6.0.1", + "uuid": "^8.3.2", + "xml": "^1.0.1" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/jest-leak-detector": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", @@ -7740,11 +7826,29 @@ "tmpl": "1.0.5" } }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -7759,6 +7863,15 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -7771,11 +7884,22 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -7784,7 +7908,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -7839,6 +7962,18 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -7942,6 +8077,15 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -8079,6 +8223,48 @@ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, + "node_modules/node-mocks-http": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.16.2.tgz", + "integrity": "sha512-2Sh6YItRp1oqewZNlck3LaFp5vbyW2u51HX2p1VLxQ9U/bG90XV8JY9O7Nk+HDd6OOn/oV3nA5Tx5k4Rki0qlg==", + "dev": true, + "dependencies": { + "accepts": "^1.3.7", + "content-disposition": "^0.5.3", + "depd": "^1.1.0", + "fresh": "^0.5.2", + "merge-descriptors": "^1.0.1", + "methods": "^1.1.2", + "mime": "^1.3.4", + "parseurl": "^1.3.3", + "range-parser": "^1.2.0", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@types/express": "^4.17.21 || ^5.0.0", + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + }, + "@types/node": { + "optional": true + } + } + }, + "node_modules/node-mocks-http/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -8298,6 +8484,15 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8758,6 +8953,15 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/raw-loader": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", @@ -9183,6 +9387,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -9555,6 +9764,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "node_modules/styled-jsx": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", @@ -10022,6 +10236,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", @@ -10441,6 +10668,12 @@ } } }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "dev": true + }, "node_modules/xml-name-validator": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", @@ -10450,6 +10683,26 @@ "node": ">=12" } }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", diff --git a/package.json b/package.json index 7d3588d5b..8482d5206 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,10 @@ "@mui/icons-material": "^6.0.2", "@reduxjs/toolkit": "^2.2.7", "autoprefixer": "^10.4.19", + "axios": "^1.7.9", "cookies": "^0.9.1", "dotenv": "^16.4.5", + "fast-xml-parser": "^4.5.1", "http-proxy-middleware": "^3.0.0", "leaflet": "^1.9.4", "leaflet-contextmenu": "^1.4.0", @@ -28,7 +30,8 @@ "redux": "^5.0.1", "redux-thunk": "^3.1.0", "tailwindcss": "^3.4.7", - "ws": "^8.18.0" + "ws": "^8.18.0", + "xml2js": "^0.6.2" }, "scripts": { "dev": "next dev", @@ -52,7 +55,9 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jest-fetch-mock": "^3.0.3", + "jest-junit": "^16.0.0", "node-fetch": "^3.3.2", + "node-mocks-http": "^1.16.2", "raw-loader": "^4.0.2" } } diff --git a/pages/api/gisStationsMeasurements.test.js b/pages/api/gisStationsMeasurements.test.js new file mode 100644 index 000000000..cbe30cbda --- /dev/null +++ b/pages/api/gisStationsMeasurements.test.js @@ -0,0 +1,67 @@ +import axios from "axios"; + +// Basis-URL des Servers +const BASE_URL = "http://10.10.0.70:3000/api/gisStationsMeasurements"; + +describe("Echte API-Integrationstests für gisStationsMeasurements", () => { + // Test 1: Erfolgreiche Anfrage mit gültigen Parametern + it("gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden", async () => { + const params = { + m: "12", // Beispiel für idMap + }; + + // Echte Anfrage an den Server senden + const response = await axios.get(BASE_URL, { params }); + + // Debugging der Header + console.log(response.headers); + + // Statuscode prüfen + expect(response.status).toBe(200); + + // Überprüfen, ob die Antwort die erwarteten JSON-Daten enthält + expect(response.data).toHaveProperty("Name"); + expect(response.data).toHaveProperty("Zeitstempel"); + expect(response.data).toHaveProperty("IdMap"); + expect(response.data).toHaveProperty("Statis"); + expect(response.data.Statis).toBeInstanceOf(Array); + + const item = response.data.Statis[0]; + expect(item).toHaveProperty("IdLD"); + expect(item).toHaveProperty("IdL"); + expect(item).toHaveProperty("IdDP"); + expect(item).toHaveProperty("Na"); + expect(item).toHaveProperty("Val"); + expect(item).toHaveProperty("Unit"); + expect(item).toHaveProperty("Gr"); + expect(item).toHaveProperty("Area_Name"); + }); + + // Test 2: Fehler bei fehlenden Parametern + it("gibt einen Fehler zurück, wenn Parameter fehlen", async () => { + try { + // Anfrage ohne Parameter + await axios.get(BASE_URL); + } catch (error) { + expect(error.response.status).toBe(400); + expect(error.response.data).toHaveProperty("error"); + + // Flexibler auf Fehlernachricht prüfen + expect(error.response.data.message).toMatch(/Fehlender Parameter|erforderlich/); + } + }); + + // Test 3: Fehler bei ungültigen Parametern + it("gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden", async () => { + try { + const params = { + m: "invalid", // Ungültige idMap + }; + + await axios.get(BASE_URL, { params }); + } catch (error) { + expect(error.response.status).toBe(500); + expect(error.response.data).toHaveProperty("error"); + } + }); +}); diff --git a/pages/api/gisStationsStaticDistrict.test.js b/pages/api/gisStationsStaticDistrict.test.js new file mode 100644 index 000000000..912c02688 --- /dev/null +++ b/pages/api/gisStationsStaticDistrict.test.js @@ -0,0 +1,66 @@ +import axios from "axios"; + +// Basis-URL des Servers +const BASE_URL = "http://10.10.0.70:3000/api/gisStationsStaticDistrict"; + +describe("Echte API-Integrationstests für gisStationsStaticDistrict", () => { + // Test 1: Erfolgreiche Anfrage mit gültigen Parametern + it("gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden", async () => { + const params = { + m: "12", // Beispiel für idMap + u: "484", // Beispiel für idUser + }; + + // Echte Anfrage an den Server senden + const response = await axios.get(BASE_URL, { params }); + + // Debugging der Header + console.log(response.headers); + + // Statuscode prüfen + expect(response.status).toBe(200); + + // Überprüfen, ob die Antwort die erwarteten Daten enthält + expect(response.data).toHaveProperty("Name"); + expect(response.data).toHaveProperty("Points"); + expect(response.data.Points).toBeInstanceOf(Array); + + const item = response.data.Points[0]; + expect(item).toHaveProperty("LD_Name"); + expect(item).toHaveProperty("Device"); + expect(item).toHaveProperty("Link"); + expect(item).toHaveProperty("Location_Name"); + expect(item).toHaveProperty("X"); + expect(item).toHaveProperty("Y"); + expect(item).toHaveProperty("Icon"); + }); + + // Test 2: Fehler bei fehlenden Parametern + it("gibt einen Fehler zurück, wenn Parameter fehlen", async () => { + try { + // Anfrage ohne Parameter + await axios.get(BASE_URL); + } catch (error) { + expect(error.response.status).toBe(400); + expect(error.response.data).toHaveProperty("error"); + + // Flexibler auf Fehlernachricht prüfen + expect(error.response.data.message).toMatch(/Fehlende Parameter|erforderlich/); + } + }); + + // Test 3: Fehler bei ungültigen Parametern + it("gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden", async () => { + try { + const params = { + m: "invalid", // Ungültige idMap + u: "invalid", // Ungültige idUser + }; + + await axios.get(BASE_URL, { params }); + } catch (error) { + expect(error.response.status).toBe(500); + expect(error.response.data).toHaveProperty("error"); + } + }); +}); diff --git a/pages/api/gisStationsStatusDistrict.test.js b/pages/api/gisStationsStatusDistrict.test.js new file mode 100644 index 000000000..08a7eeef0 --- /dev/null +++ b/pages/api/gisStationsStatusDistrict.test.js @@ -0,0 +1,58 @@ +import axios from "axios"; + +// Basis-URL des Servers +const BASE_URL = "http://10.10.0.70:3000/api/gisStationsStatusDistrict"; + +describe("Echte API-Integrationstests", () => { + it("gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden", async () => { + const params = { + m: "12", + u: "484", + }; + + // Echte Anfrage an den Server senden + const response = await axios.get(BASE_URL, { params }); + + // Antwortstatus prüfen + expect(response.status).toBe(200); + + // Antwortdaten prüfen + expect(response.data).toHaveProperty("Name"); + expect(response.data).toHaveProperty("Statis"); + expect(response.data.Statis).toBeInstanceOf(Array); + + const item = response.data.Statis[0]; + expect(item).toHaveProperty("IdLD"); + expect(item).toHaveProperty("Na"); + expect(item).toHaveProperty("Le"); + expect(item).toHaveProperty("Co"); + expect(item).toHaveProperty("Me"); + expect(item).toHaveProperty("Feld"); + expect(item).toHaveProperty("Icon"); + }); + + it("gibt einen Fehler zurück, wenn Parameter fehlen", async () => { + try { + // Anfrage ohne Parameter + await axios.get(BASE_URL); + } catch (error) { + expect(error.response.status).toBe(400); + expect(error.response.data).toHaveProperty("error"); + expect(error.response.data).toHaveProperty("message"); + } + }); + + it("gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden", async () => { + try { + const params = { + m: "invalid", + u: "invalid", + }; + + await axios.get(BASE_URL, { params }); + } catch (error) { + expect(error.response.status).toBe(500); + expect(error.response.data).toHaveProperty("error"); + } + }); +}); diff --git a/pages/api/gisSystemStatic.test.js b/pages/api/gisSystemStatic.test.js new file mode 100644 index 000000000..3a8169b18 --- /dev/null +++ b/pages/api/gisSystemStatic.test.js @@ -0,0 +1,67 @@ +import axios from "axios"; + +// Basis-URL des Servers +const BASE_URL = "http://10.10.0.70:3000/api/gisSystemStatic"; + +describe("Echte API-Integrationstests für gisSystemStatic", () => { + // Test 1: Erfolgreiche Anfrage mit gültigen Parametern + it("gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden", async () => { + const params = { + m: "12", // Beispiel für idMap + u: "484", // Beispiel für idUser + }; + + // Echte Anfrage an den Server senden + const response = await axios.get(BASE_URL, { params }); + + // Debugging der Header + console.log(response.headers); + + // Statuscode prüfen + expect(response.status).toBe(200); + + // Überprüfen, ob die Antwort die erwarteten JSON-Daten enthält + expect(response.data).toHaveProperty("Name"); + expect(response.data).toHaveProperty("Zeitstempel"); + expect(response.data).toHaveProperty("IdMap"); + expect(response.data).toHaveProperty("Systems"); + expect(response.data.Systems).toBeInstanceOf(Array); + + // Erster Eintrag prüfen + const item = response.data.Systems[0]; + expect(item).toHaveProperty("IdSystem"); + expect(item).toHaveProperty("Name"); + expect(item).toHaveProperty("Longname"); + expect(item).toHaveProperty("Allow"); + expect(item).toHaveProperty("Icon"); + }); + + // Test 2: Fehler bei fehlenden Parametern + it("gibt einen Fehler zurück, wenn Parameter fehlen", async () => { + try { + // Anfrage ohne Parameter + await axios.get(BASE_URL); + } catch (error) { + expect(error.response.status).toBe(400); + expect(error.response.data).toHaveProperty("error"); + + // Flexibler auf Fehlernachricht prüfen + expect(error.response.data.message).toMatch(/Fehlende Parameter|erforderlich/); + } + }); + + // Test 3: Fehler bei ungültigen Parametern + it("gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden", async () => { + try { + const params = { + m: "invalid", // Ungültige idMap + u: "invalid", // Ungültige idUser + }; + + await axios.get(BASE_URL, { params }); + } catch (error) { + expect(error.response.status).toBe(500); + expect(error.response.data).toHaveProperty("error"); + } + }); +}); diff --git a/reports/junit/junit.xml b/reports/junit/junit.xml new file mode 100644 index 000000000..0d3e866e3 --- /dev/null +++ b/reports/junit/junit.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/utils/openInNewTab.test.js b/utils/openInNewTab.test.js deleted file mode 100644 index e82fa7e8e..000000000 --- a/utils/openInNewTab.test.js +++ /dev/null @@ -1,54 +0,0 @@ -// utils/openInNewTab.test.js -import { openInNewTab } from "./openInNewTab"; - -// Leaflet manuell mocken -global.L = { - Marker: class { - constructor(options) { - this.options = options || {}; - } - }, - Polyline: class { - constructor(options) { - this.options = options || {}; - } - }, -}; - -describe("Integrationstest für openInNewTab", () => { - const mockWindowOpen = jest.fn(); - - beforeAll(() => { - global.window = Object.create(window); - window.open = mockWindowOpen; - delete window.location; - window.location = new URL("http://10.10.0.13"); - }); - - afterEach(() => { - mockWindowOpen.mockClear(); - }); - - it("soll den Link korrekt für einen Marker öffnen", () => { - const marker = new L.Marker({ link: "cpl.aspx?ver=35&kue=24&id=50922" }); - openInNewTab(null, marker); - - expect(mockWindowOpen).toHaveBeenCalledWith("http://10.10.0.13/talas5/devices/cpl.aspx?ver=35&kue=24&id=50922", "_blank"); - }); - - it("soll den Link korrekt für eine Polyline öffnen", () => { - const polyline = new L.Polyline({ idLD: 50922 }); - openInNewTab(null, polyline); - - expect(mockWindowOpen).toHaveBeenCalledWith("http://10.10.0.13/talas5/devices/cpl.aspx?id=50922", "_blank"); - }); - - it("soll einen Fehler ausgeben, wenn kein Link gefunden wird", () => { - console.error = jest.fn(); - - openInNewTab(); - - expect(console.error).toHaveBeenCalledWith("Fehler: Es wurde kein gültiger Link gefunden."); - expect(mockWindowOpen).not.toHaveBeenCalled(); - }); -});