feat: Proxy-APIs und Integrationstests für WebServices hinzugefügt

- 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.
This commit is contained in:
ISA
2025-01-03 14:02:29 +01:00
parent 2a1f885190
commit d7978790e1
13 changed files with 600 additions and 171 deletions

View File

@@ -0,0 +1,29 @@
const mockXmlData = `
<root>
<Name>Liste aller Status der Geräte</Name>
<Zeitstempel>2025-01-03T11:26:11.777</Zeitstempel>
<IdMap>12</IdMap>
<Statis>
<Item>
<IdLD>50922</IdLD>
<Na>system</Na>
<Le>4</Le>
<Co>#FF00FF</Co>
<Me>Eingang DE 01 kommend</Me>
<Feld>4</Feld>
<Icon>0</Icon>
</Item>
<Item>
<IdLD>50922</IdLD>
<Na>system</Na>
<Le>4</Le>
<Co>#FF00FF</Co>
<Me>Eingang DE 05 kommend</Me>
<Feld>4</Feld>
<Icon>0</Icon>
</Item>
</Statis>
</root>
`;
export default mockXmlData;

View File

@@ -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;

View File

@@ -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(
<RecoilRoot initializeState={({ set }) => set(mapLayersState, mockState)}>
<MapComponent />
</RecoilRoot>
);
// 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(
<RecoilRoot initializeState={({ set }) => set(mapLayersState, mockState)}>
<MapComponent />
</RecoilRoot>
);
// 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);
});
});

View File

@@ -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();
});
});

View File

@@ -1,18 +1,13 @@
module.exports = {
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
testEnvironment: "jsdom",
reporters: ["default", ["jest-junit", { outputDirectory: "./test-results/junit", outputName: "results.xml" }]],
testPathIgnorePatterns: ["<rootDir>/.next/", "<rootDir>/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$": "<rootDir>/__mocks__/leaflet.js", // Leaflet Mock hinzufügen
"^leaflet.smooth_marker_bouncing$": "<rootDir>/__mocks__/leaflet.smooth_marker_bouncing.js", // Smooth Marker Mock
},
};

271
package-lock.json generated
View File

@@ -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",

View File

@@ -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"
}
}

View File

@@ -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");
}
});
});

View File

@@ -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");
}
});
});

View File

@@ -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");
}
});
});

View File

@@ -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");
}
});
});

35
reports/junit/junit.xml Normal file
View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="jest tests" tests="12" failures="0" errors="0" time="2.098">
<testsuite name="Echte API-Integrationstests" errors="0" failures="0" skipped="0" timestamp="2025-01-03T12:58:59" time="1.242" tests="3">
<testcase classname="Echte API-Integrationstests gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden" name="Echte API-Integrationstests gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden" time="0.087">
</testcase>
<testcase classname="Echte API-Integrationstests gibt einen Fehler zurück, wenn Parameter fehlen" name="Echte API-Integrationstests gibt einen Fehler zurück, wenn Parameter fehlen" time="0.068">
</testcase>
<testcase classname="Echte API-Integrationstests gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden" name="Echte API-Integrationstests gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden" time="0.034">
</testcase>
</testsuite>
<testsuite name="Echte API-Integrationstests für gisStationsMeasurements" errors="0" failures="0" skipped="0" timestamp="2025-01-03T12:58:59" time="1.3" tests="3">
<testcase classname="Echte API-Integrationstests für gisStationsMeasurements gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden" name="Echte API-Integrationstests für gisStationsMeasurements gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden" time="0.12">
</testcase>
<testcase classname="Echte API-Integrationstests für gisStationsMeasurements gibt einen Fehler zurück, wenn Parameter fehlen" name="Echte API-Integrationstests für gisStationsMeasurements gibt einen Fehler zurück, wenn Parameter fehlen" time="0.092">
</testcase>
<testcase classname="Echte API-Integrationstests für gisStationsMeasurements gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden" name="Echte API-Integrationstests für gisStationsMeasurements gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden" time="0.026">
</testcase>
</testsuite>
<testsuite name="Echte API-Integrationstests für gisStationsStaticDistrict" errors="0" failures="0" skipped="0" timestamp="2025-01-03T12:58:59" time="1.306" tests="3">
<testcase classname="Echte API-Integrationstests für gisStationsStaticDistrict gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden" name="Echte API-Integrationstests für gisStationsStaticDistrict gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden" time="0.155">
</testcase>
<testcase classname="Echte API-Integrationstests für gisStationsStaticDistrict gibt einen Fehler zurück, wenn Parameter fehlen" name="Echte API-Integrationstests für gisStationsStaticDistrict gibt einen Fehler zurück, wenn Parameter fehlen" time="0.057">
</testcase>
<testcase classname="Echte API-Integrationstests für gisStationsStaticDistrict gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden" name="Echte API-Integrationstests für gisStationsStaticDistrict gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden" time="0.03">
</testcase>
</testsuite>
<testsuite name="Echte API-Integrationstests für gisSystemStatic" errors="0" failures="0" skipped="0" timestamp="2025-01-03T12:58:59" time="1.558" tests="3">
<testcase classname="Echte API-Integrationstests für gisSystemStatic gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden" name="Echte API-Integrationstests für gisSystemStatic gibt JSON-Daten zurück, wenn gültige Parameter übergeben werden" time="0.205">
</testcase>
<testcase classname="Echte API-Integrationstests für gisSystemStatic gibt einen Fehler zurück, wenn Parameter fehlen" name="Echte API-Integrationstests für gisSystemStatic gibt einen Fehler zurück, wenn Parameter fehlen" time="0.048">
</testcase>
<testcase classname="Echte API-Integrationstests für gisSystemStatic gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden" name="Echte API-Integrationstests für gisSystemStatic gibt einen Serverfehler zurück, wenn ungültige Parameter verwendet werden" time="0.018">
</testcase>
</testsuite>
</testsuites>

View File

@@ -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();
});
});