From f19b0bafb51ff3cbe0f151bdf98a314da8588fe4 Mon Sep 17 00:00:00 2001 From: Jan Loewe <jan.loewe@ptb.de> Date: Tue, 16 May 2023 09:22:39 +0000 Subject: [PATCH] Add tests --- .eslintrc.json | 2 +- .gitignore | 3 + .gitlab-ci.yml | 56 ++ .idea/git_toolbox_prj.xml | 5 + .idea/inspectionProfiles/Project_Default.xml | 6 + .idea/jsLinters/eslint.xml | 6 + .yarnrc.yml | 1 + jest.config.ts | 10 + package-lock.json | Bin 303276 -> 0 bytes package.json | 42 +- tests/Arbitraries.ts | 17 + tests/DCC/AdministrativeData.Items.test.ts | 117 +++ ...dministrativeData.SoftwareListType.test.ts | 41 + tests/DCC/AdministrativeData.test.ts | 19 + .../DigitalCalibrationCertificateType.test.ts | 21 + ...strativeData.CalibrationLaboratory.test.ts | 84 ++ .../AdministrativeData.CoreDataType.test.ts | 118 +++ .../AdministrativeData.Customer.test.ts | 70 ++ .../AdministrativeData.Items.test.ts | 117 +++ .../AdministrativeData.RespPersons.test.ts | 56 ++ ...dministrativeData.SoftwareListType.test.ts | 37 + .../AdministrativeData.Statements.test.ts | 127 +++ .../DigitalCalibrationCertificateType.test.ts | 21 + ...surementResult.InfluenceConditions.test.ts | 218 ++++++ ...surementResult.MeasuringEquipments.test.ts | 58 ++ ...mentResults.MeasurementResult.Name.test.ts | 35 + ...tResults.MeasurementResult.Results.test.ts | 339 ++++++++ ...ults.MeasurementResult.UsedMethods.test.ts | 44 ++ .../AdministrativeData.Items_variant.test.ts | 37 + ...inistrativeData.Statements_variant.test.ts | 95 +++ ...strativeData.CalibrationLaboratory.test.ts | 80 ++ .../AdministrativeData.CoreDataType.test.ts | 120 +++ .../AdministrativeData.Customer.test.ts | 77 ++ .../AdministrativeData.Items.test.ts | 117 +++ .../AdministrativeData.RespPersons.test.ts | 56 ++ ...dministrativeData.SoftwareListType.test.ts | 39 + .../AdministrativeData.Statements.test.ts | 213 +++++ .../DigitalCalibrationCertificateType.test.ts | 21 + ...surementResult.InfluenceConditions.test.ts | 249 ++++++ ...surementResult.MeasuringEquipments.test.ts | 58 ++ ...mentResults.MeasurementResult.Name.test.ts | 35 + ...tResults.MeasurementResult.Results.test.ts | 302 +++++++ ...ults.MeasurementResult.UsedMethods.test.ts | 81 ++ ...strativeData.CalibrationLaboratory.test.ts | 84 ++ .../AdministrativeData.CoreDataType.test.ts | 128 +++ .../AdministrativeData.Customer.test.ts | 70 ++ .../AdministrativeData.Items.test.ts | 144 ++++ ...ministrativeData.RefTypeDefinitons.test.ts | 72 ++ .../AdministrativeData.RespPersons.test.ts | 56 ++ ...dministrativeData.SoftwareListType.test.ts | 60 ++ .../AdministrativeData.Statements.test.ts | 127 +++ .../DigitalCalibrationCertificateType.test.ts | 21 + ...surementResult.InfluenceConditions.test.ts | 218 ++++++ ...surementResult.MeasuringEquipments.test.ts | 58 ++ ...mentResults.MeasurementResult.Name.test.ts | 35 + ...tResults.MeasurementResult.Results.test.ts | 737 ++++++++++++++++++ ...ults.MeasurementResult.UsedMethods.test.ts | 44 ++ ...surementResult.InfluenceConditions.test.ts | 249 ++++++ ...surementResult.MeasuringEquipments.test.ts | 58 ++ ...mentResults.MeasurementResult.Name.test.ts | 35 + ...tResults.MeasurementResult.Results.test.ts | 302 +++++++ ...ults.MeasurementResult.UsedMethods.test.ts | 81 ++ ...strativeData.CalibrationLaboratory.test.ts | 34 + .../AdministrativeData.CoreDataType.test.ts | 116 +++ .../AdministrativeData.Customer.test.ts | 42 + .../AdministrativeData.Items.test.ts | 64 ++ .../AdministrativeData.RespPersons.test.ts | 37 + ...dministrativeData.SoftwareListType.test.ts | 41 + .../DigitalCalibrationCertificateType.test.ts | 21 + ...mentResults.MeasurementResult.Name.test.ts | 35 + ...tResults.MeasurementResult.Results.test.ts | 100 +++ .../CalibrationLaboratory.ts | 78 ++ .../common/AdministrativeData/CoreDataType.ts | 117 +++ .../common/AdministrativeData/RespPersons.ts | 19 + tests/DCC/common/Types/ContactType.ts | 72 ++ tests/DCC/common/Types/DataType.ts | 23 + tests/DCC/common/Types/RespPersonType.ts | 28 + tests/DCC/common/Types/RichContentType.ts | 25 + tests/DCC/common/Types/StatementListType.ts | 18 + .../DCC/common/Types/StatementMetaDataType.ts | 72 ++ tests/DCCDocument.test.ts | 30 +- tests/GP_Temperature/CharsXMLList.test.ts | 25 + tests/GP_Temperature/noQuantity.test.ts | 56 ++ tests/XMLEnvironment.ts | 44 ++ tests/index.d.ts | 12 + tests/resources/GP_Temperature_Simplified.xml | 352 +++++++++ .../GP_Temperature_Simplified_variant.xml | 365 +++++++++ tests/resources/GP_Temperature_Typical.xml | 441 +++++++++++ tests/resources/GP_Temperature_v3.2.0_DCC.xml | 540 +++++++++++++ tests/resources/Test_DCC_Minimal.xml | 108 +++ .../example.xml.ts => resources/example.xml} | 40 +- tests/tsconfig.json | 7 + tests/util.ts | 36 + tsconfig.json | 6 +- yarn.lock | Bin 0 -> 202139 bytes 95 files changed, 8781 insertions(+), 52 deletions(-) create mode 100644 .gitlab-ci.yml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/jsLinters/eslint.xml create mode 100644 .yarnrc.yml create mode 100644 jest.config.ts delete mode 100644 package-lock.json create mode 100644 tests/Arbitraries.ts create mode 100644 tests/DCC/AdministrativeData.Items.test.ts create mode 100644 tests/DCC/AdministrativeData.SoftwareListType.test.ts create mode 100644 tests/DCC/AdministrativeData.test.ts create mode 100644 tests/DCC/DigitalCalibrationCertificateType.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.CalibrationLaboratory.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.CoreDataType.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Customer.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Items.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.RespPersons.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.SoftwareListType.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Statements.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/DigitalCalibrationCertificateType.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.Name.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.Results.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.UsedMethods.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified_variant/AdministrativeData.Items_variant.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Simplified_variant/AdministrativeData.Statements_variant.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.CalibrationLaboratory.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.CoreDataType.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Customer.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Items.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.RespPersons.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.SoftwareListType.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Statements.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/DigitalCalibrationCertificateType.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.Name.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.Results.test.ts create mode 100644 tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.UsedMethods.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.CalibrationLaboratory.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.CoreDataType.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Customer.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Items.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.RefTypeDefinitons.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.RespPersons.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.SoftwareListType.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Statements.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/DigitalCalibrationCertificateType.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.Name.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.Results.test.ts create mode 100644 tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.UsedMethods.test.ts create mode 100644 tests/DCC/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts create mode 100644 tests/DCC/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts create mode 100644 tests/DCC/MeasurementResults.MeasurementResult.Name.test.ts create mode 100644 tests/DCC/MeasurementResults.MeasurementResult.Results.test.ts create mode 100644 tests/DCC/MeasurementResults.MeasurementResult.UsedMethods.test.ts create mode 100644 tests/DCC/Test_DCC_Minimal/AdministrativeData.CalibrationLaboratory.test.ts create mode 100644 tests/DCC/Test_DCC_Minimal/AdministrativeData.CoreDataType.test.ts create mode 100644 tests/DCC/Test_DCC_Minimal/AdministrativeData.Customer.test.ts create mode 100644 tests/DCC/Test_DCC_Minimal/AdministrativeData.Items.test.ts create mode 100644 tests/DCC/Test_DCC_Minimal/AdministrativeData.RespPersons.test.ts create mode 100644 tests/DCC/Test_DCC_Minimal/AdministrativeData.SoftwareListType.test.ts create mode 100644 tests/DCC/Test_DCC_Minimal/DigitalCalibrationCertificateType.test.ts create mode 100644 tests/DCC/Test_DCC_Minimal/MeasurementResults.MeasurementResult.Name.test.ts create mode 100644 tests/DCC/Test_DCC_Minimal/MeasurementResults.MeasurementResult.Results.test.ts create mode 100644 tests/DCC/common/AdministrativeData/CalibrationLaboratory.ts create mode 100644 tests/DCC/common/AdministrativeData/CoreDataType.ts create mode 100644 tests/DCC/common/AdministrativeData/RespPersons.ts create mode 100644 tests/DCC/common/Types/ContactType.ts create mode 100644 tests/DCC/common/Types/DataType.ts create mode 100644 tests/DCC/common/Types/RespPersonType.ts create mode 100644 tests/DCC/common/Types/RichContentType.ts create mode 100644 tests/DCC/common/Types/StatementListType.ts create mode 100644 tests/DCC/common/Types/StatementMetaDataType.ts create mode 100644 tests/GP_Temperature/CharsXMLList.test.ts create mode 100644 tests/GP_Temperature/noQuantity.test.ts create mode 100644 tests/XMLEnvironment.ts create mode 100644 tests/index.d.ts create mode 100644 tests/resources/GP_Temperature_Simplified.xml create mode 100644 tests/resources/GP_Temperature_Simplified_variant.xml create mode 100644 tests/resources/GP_Temperature_Typical.xml create mode 100644 tests/resources/GP_Temperature_v3.2.0_DCC.xml create mode 100644 tests/resources/Test_DCC_Minimal.xml rename tests/{Resources/example.xml.ts => resources/example.xml} (93%) create mode 100644 tests/tsconfig.json create mode 100644 tests/util.ts create mode 100644 yarn.lock diff --git a/.eslintrc.json b/.eslintrc.json index 8a39c34..cfec66a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,4 +10,4 @@ "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended" ] -} \ No newline at end of file +} diff --git a/.gitignore b/.gitignore index d583f86..ef05b8c 100644 --- a/.gitignore +++ b/.gitignore @@ -612,3 +612,6 @@ $RECYCLE.BIN/ /.tgitconfig lib +junit.xml + +.yarn/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..43d696f --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,56 @@ +image: node:18.15.0 + +stages: + - test + +# === Caches === +.yarn-cache: &yarn-cache + key: yarn-$CI_JOB_IMAGE + paths: + - .yarn + +# === Proxy === +# Description: sets up the proxy needed for the runner inside of the PTB. Produces a build.env that is used in the next jobs +proxy: + stage: .pre + script: + - touch build.env + - if [[ "$CI_RUNNER_TAGS" == *"behind_proxy"* ]]; then + - echo "behind_proxy=true" >> build.env + - echo "http_proxy=http://webproxy.bs.ptb.de:8080/" >> build.env + - echo "https_proxy=http://webproxy.bs.ptb.de:8080/" >> build.env + - fi + artifacts: + reports: + dotenv: build.env + + +# === Yarn Install === +# Description: installs and caches dependencies +.yarn-install: &yarn-install + - corepack enable + # proxy settings + - if [[ "$behind_proxy" == true ]]; then + - npm config set proxy $http_proxy + - npm config set https-proxy $https_proxy + - yarn config set -H httpProxy $http_proxy + - yarn config set -H httpsProxy $https_proxy + - fi + # install deps + - yarn install --immutable + +# === Job: Unit Tests === +# Description: this job runs the unit tests +test: + stage: test + needs: ["proxy"] + script: + - *yarn-install + - yarn run test:unit --ci + cache: + - <<: *yarn-cache + artifacts: + when: always + reports: + junit: + - junit.xml diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml index b382006..bcb1d9d 100644 --- a/.idea/git_toolbox_prj.xml +++ b/.idea/git_toolbox_prj.xml @@ -11,5 +11,10 @@ <option name="enabled" value="true" /> </CommitMessageValidationOverride> </option> + <option name="commitMessageValidationEnabledOverride"> + <BoolValueOverride> + <option name="enabled" value="true" /> + </BoolValueOverride> + </option> </component> </project> \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" /> + </profile> +</component> \ No newline at end of file diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml new file mode 100644 index 0000000..541945b --- /dev/null +++ b/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="EslintConfiguration"> + <option name="fix-on-save" value="true" /> + </component> +</project> \ No newline at end of file diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 0000000..3186f3f --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..85289d3 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,10 @@ +import type { JestConfigWithTsJest } from "ts-jest"; + +const config: JestConfigWithTsJest = { + preset: "ts-jest", + testEnvironment: "node", + reporters: ["default", "jest-junit"], + coverageProvider: "v8", +}; + +export default config; diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 5f2c10e590391b41038f3c19919e003c6dacf6c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 303276 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 M|Nr`r|N4*r10I(sVE_OC diff --git a/package.json b/package.json index 98f1ca0..5e495af 100644 --- a/package.json +++ b/package.json @@ -11,31 +11,36 @@ "fix:prettier": "prettier \"src/**/*.ts\" --write", "fix:lint": "eslint src --ext .ts --fix", "test": "run-s test:*", - "test:unit": "mocha -r ts-node/register tests/**/*.test.ts", + "test:unit": "jest", "test:lint": "eslint src --ext .ts", "test:prettier": "prettier \"src/**/*.ts\" --list-different", - "coverage": "nyc -r lcov -e .ts -x \"*.test.ts\" mocha -r ts-node/register tests/**/*.test.ts && nyc report", - "prepare": "npm run build", - "prepublishOnly": "npm run test", - "preversion": "npm run test" + "prepare": "yarn run build", + "prepublishOnly": "yarn run test", + "preversion": "yarn run test" }, "dependencies": { "xml-js": "^1.6.11" }, "devDependencies": { - "@types/chai": "^4.3.0", - "@types/mocha": "^9.1.0", - "@typescript-eslint/eslint-plugin": "^5.11.0", - "@typescript-eslint/parser": "^5.11.0", - "chai": "^4.3.6", - "eslint": "^8.8.0", - "eslint-config-prettier": "^8.3.0", - "mocha": "^9.2.0", + "@jest/globals": "^29.5.0", + "@types/jest": "^29.5.1", + "@types/node": "^18.16.2", + "@typescript-eslint/eslint-plugin": "^5.56.0", + "@typescript-eslint/parser": "^5.56.0", + "eslint": "^8.36.0", + "eslint-config-prettier": "^8.8.0", + "fast-check": "^3.7.1", + "jest": "^29.5.0", + "jest-environment-node": "^29.5.0", + "jest-junit": "^16.0.0", + "jsdom": "^21.1.1", + "lodash": "^4.17.21", "npm-run-all": "^4.1.5", - "nyc": "^15.1.0", - "prettier": "^2.5.1", - "ts-node": "^10.5.0", - "typescript": "^4.5.5" + "prettier": "^2.8.6", + "ts-jest": "^29.1.0", + "ts-node": "^10.9.1", + "typescript": "^4.9.5", + "xpath-ts": "^1.3.13" }, "publishConfig": { "@d-ptb:registry": "https://gitlab1.ptb.de/api/v4/projects/105/packages/npm/" @@ -46,5 +51,6 @@ "!**/*.json", "LICENSE", "README.md" - ] + ], + "packageManager": "yarn@3.5.0" } diff --git a/tests/Arbitraries.ts b/tests/Arbitraries.ts new file mode 100644 index 0000000..be7453c --- /dev/null +++ b/tests/Arbitraries.ts @@ -0,0 +1,17 @@ +import * as fc from "fast-check"; + +export const string_ISO3166_1 = () => + fc + .integer({ + min: "A".charCodeAt(0), + max: "Z".charCodeAt(0), + }) + .map(String.fromCharCode); + +export const string_ISO639_1 = () => + fc + .integer({ + min: "a".charCodeAt(0), + max: "z".charCodeAt(0), + }) + .map(String.fromCharCode); diff --git a/tests/DCC/AdministrativeData.Items.test.ts b/tests/DCC/AdministrativeData.Items.test.ts new file mode 100644 index 0000000..79dfe54 --- /dev/null +++ b/tests/DCC/AdministrativeData.Items.test.ts @@ -0,0 +1,117 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +import { select, toTextArr, toTextContentArr } from "../util"; +import { ItemType, DCCDocument, IdentificationType } from "../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:items"; +const xpath = { + items: { + item: { + name: { + content: `${base}/dcc:item[1]/dcc:name/dcc:content`, + }, + manufacturer: { + name: { + content: `${base}/dcc:item[1]/dcc:manufacturer/dcc:name/dcc:content`, + }, + }, + model: `string(${base}/dcc:item[1]/dcc:model)`, + + identifications: { + identification1: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + identification2: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:name/dcc:content`, + }, + }, + identification3: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:name/dcc:content`, + }, + }, + }, + }, + }, +}; + +describe("ItemType", () => { + let dcc: DCCDocument, item: ItemType, identification1, identification2, identification3: IdentificationType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + item = dcc.digitalCalibrationCertificate.administrativeData.items.item[0]; + identification1 = item.identifications.identification[0]; + identification2 = item.identifications.identification[1]; + identification3 = item.identifications.identification[2]; + }); + + test("should get correct item name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.name.content, dom); + expect(toTextArr(item.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item manufacturer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.manufacturer.name.content, dom); + expect(toTextArr(item.manufacturer.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item model from XML", () => { + expect(item.model._text).toBe(select(xpath.items.item.model, dom)); + }); + + test("should get correct identification 1 issuer from XML", () => { + expect(identification1.issuer._text).toBe(select(xpath.items.item.identifications.identification1.issuer, dom)); + }); + + test("should get correct identification 1 value from XML", () => { + expect(identification1.value._text).toBe(select(xpath.items.item.identifications.identification1.value, dom)); + }); + + test("should get correct identification 1 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification1.name.content, dom); + expect(toTextArr(identification1.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct identification 2 issuer from XML", () => { + expect(identification2.issuer._text).toBe(select(xpath.items.item.identifications.identification2.issuer, dom)); + }); + + test("should get correct identification 2 value from XML", () => { + expect(identification2.value._text).toBe(select(xpath.items.item.identifications.identification2.value, dom)); + }); + + test("should get correct identification 2 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification2.name.content, dom); + expect(toTextArr(identification2.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct identification 3 issuer from XML", () => { + expect(identification3.issuer._text).toBe(select(xpath.items.item.identifications.identification3.issuer, dom)); + }); + + test("should get correct identification 3 value from XML", () => { + expect(identification3.value._text).toBe(select(xpath.items.item.identifications.identification3.value, dom)); + }); + + test("should get correct identification 3 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification3.name.content, dom); + expect(toTextArr(identification3.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/AdministrativeData.SoftwareListType.test.ts b/tests/DCC/AdministrativeData.SoftwareListType.test.ts new file mode 100644 index 0000000..6139807 --- /dev/null +++ b/tests/DCC/AdministrativeData.SoftwareListType.test.ts @@ -0,0 +1,41 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +import { select, toTextArr, toTextContentArr } from "../util"; +import { SoftwareListType, DCCDocument, SoftwareType } from "../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:dccSoftware/dcc:software"; +const xpath = { + software: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + release: `string(${base}/dcc:release)`, + type: `string(${base}/dcc:type)`, + description: `${base}/dcc:description`, + _id: `${base}/@id`, + _refType: `${base}/@refType`, + }, +}; + +describe("DccSoftwareType", () => { + let dcc: DCCDocument, dccSoftware: SoftwareListType, software: SoftwareType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + dccSoftware = dcc.digitalCalibrationCertificate.administrativeData.dccSoftware; + software = dccSoftware.software[0]; + }); + + test("should get correct software name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.software.name.content, dom); + expect(toTextArr(software.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct software release version of software from XML", () => { + expect(software.release._text).toBe(select(xpath.software.release, dom)); + }); +}); diff --git a/tests/DCC/AdministrativeData.test.ts b/tests/DCC/AdministrativeData.test.ts new file mode 100644 index 0000000..b6f6ade --- /dev/null +++ b/tests/DCC/AdministrativeData.test.ts @@ -0,0 +1,19 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +import { testCalibrationLaboratory } from "./common/AdministrativeData/CalibrationLaboratory"; +import { testCoreData } from "./common/AdministrativeData/CoreDataType"; +import { testContactType } from "./common/Types/ContactType"; +import { testRespPersonListType } from "./common/AdministrativeData/RespPersons"; +import { testStatementListType } from "./common/Types/StatementListType"; + +describe(`[example.xml] AdministrativeData`, () => { + const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData"; + testCalibrationLaboratory(); + testCoreData(); + testContactType(`${base}/dcc:customer`, (dcc) => dcc.digitalCalibrationCertificate.administrativeData.customer); + testRespPersonListType(); + testStatementListType(`${base}/dcc:statements`, (dcc) => dcc.digitalCalibrationCertificate.administrativeData.statements); +}); diff --git a/tests/DCC/DigitalCalibrationCertificateType.test.ts b/tests/DCC/DigitalCalibrationCertificateType.test.ts new file mode 100644 index 0000000..eaceec3 --- /dev/null +++ b/tests/DCC/DigitalCalibrationCertificateType.test.ts @@ -0,0 +1,21 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +import { select } from "../util"; + +const VERSION_XPATH = "string(/dcc:digitalCalibrationCertificate/@schemaVersion)"; + +describe("DigitalCalibrationCertificateType", () => { + let xml, dcc, dom; + + beforeEach(() => { + ({ xml, dcc, dom } = xmlEnv.recreateEnv()); + }); + + test("should get correct schemaVersion from XML", () => { + const expectedVersion = select(VERSION_XPATH, dom); + expect(dcc.digitalCalibrationCertificate._attr.schemaVersion).toBe(expectedVersion); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.CalibrationLaboratory.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.CalibrationLaboratory.test.ts new file mode 100644 index 0000000..0bf3cce --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.CalibrationLaboratory.test.ts @@ -0,0 +1,84 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { CalibrationLaboratoryType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:calibrationLaboratory/dcc:contact"; +const xpath = { + name: `string(${base}/dcc:name/dcc:content)`, + eMail: `string(${base}/dcc:eMail)`, + phone: `string(${base}/dcc:phone)`, + fax: `string(${base}/dcc:fax)`, + location: { + city: `${base}/dcc:location/dcc:city`, + countryCode: `${base}/dcc:location/dcc:countryCode`, + postCode: `${base}/dcc:location/dcc:postCode`, + street: `${base}/dcc:location/dcc:street`, + streetNo: `${base}/dcc:location/dcc:streetNo`, + further: `${base}/dcc:location/dcc:further/dcc:content`, + }, +}; + +describe("GP_DCC_Temperature_Simplified: CalibrationLaboratoryType", () => { + let dcc: DCCDocument, calibrationLaboratory: CalibrationLaboratoryType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + calibrationLaboratory = dcc.digitalCalibrationCertificate.administrativeData.calibrationLaboratory; + }); + + test("should get correct name from XML", () => { + expect(calibrationLaboratory.contact.name.content[0]._text).toBe(select(xpath.name, dom)); + }); + + test("should get correct eMail from XML", () => { + expect(calibrationLaboratory.contact.eMail._text).toBe(select(xpath.eMail, dom)); + }); + + test("should get correct phone from XML", () => { + expect(calibrationLaboratory.contact.phone._text).toBe(select(xpath.phone, dom)); + }); + + test("should get correct fax from XML", () => { + expect(calibrationLaboratory.contact.fax._text).toBe(select(xpath.fax, dom)); + }); + + test("should get correct city from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.city, dom); + expect(toTextArr(calibrationLaboratory.contact.location.city)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct countryCode from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.countryCode, dom); + expect(toTextArr(calibrationLaboratory.contact.location.countryCode)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct postCode from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.postCode, dom); + expect(toTextArr(calibrationLaboratory.contact.location.postCode)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct street from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.street, dom); + expect(toTextArr(calibrationLaboratory.contact.location.street)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct streetNo from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.streetNo, dom); + expect(toTextArr(calibrationLaboratory.contact.location.streetNo)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct further element from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.further, dom); + expect(toTextArr(calibrationLaboratory.contact.location.further[0].content)).toEqual(toTextContentArr(expected)); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.CoreDataType.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.CoreDataType.test.ts new file mode 100644 index 0000000..0c3aaf0 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.CoreDataType.test.ts @@ -0,0 +1,118 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import * as fc from "fast-check"; +import { indexOf, select, toTextArr, toTextContentArr } from "../../util"; +import { CoreDataType, DCCDocument, DCCXMLElement } from "../../../src"; +import { string_ISO639_1 } from "../../Arbitraries"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:coreData"; +const xpath = { + coreData: { + countryCodeISO3166_1: `string(${base}/dcc:countryCodeISO3166_1)`, + usedLangCodeISO639_1: `${base}/dcc:usedLangCodeISO639_1`, + mandatoryLangCodeISO639_1: `${base}/dcc:mandatoryLangCodeISO639_1`, + uniqueIdentifier: `string(${base}/dcc:uniqueIdentifier)`, + identifications: { + identification: { + issuer: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + }, + beginPerformanceDate: `string(${base}/dcc:beginPerformanceDate)`, + endPerformanceDate: `string(${base}/dcc:endPerformanceDate)`, + performanceLocation: `string(${base}/dcc:performanceLocation)`, + }, +}; + +describe("GP_DCC_Temperature_Simplified: CoreDataType", () => { + let dcc: DCCDocument, coreData: CoreDataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + coreData = dcc.digitalCalibrationCertificate.administrativeData.coreData; + }); + + test("should get correct countryCodeISO3166_1 from XML", () => { + expect(coreData.countryCodeISO3166_1._text).toBe(select(xpath.coreData.countryCodeISO3166_1, dom)); + }); + + test("should get correct usedLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom); + expect(toTextArr(coreData.usedLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct mandatoryLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.mandatoryLangCodeISO639_1, dom); + expect(toTextArr(coreData.mandatoryLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct unique identifier from XML", () => { + expect(coreData.uniqueIdentifier._text).toBe(select(xpath.coreData.uniqueIdentifier, dom)); + }); + + test("should get correct identification issuer from XML", () => { + expect(coreData.identifications.identification[0].issuer._text).toBe(select(xpath.coreData.identifications.identification.issuer, dom)); + }); + + test("should get correct identification value from XML", () => { + expect(coreData.identifications.identification[0].value._text).toBe(select(xpath.coreData.identifications.identification.value, dom)); + }); + + test("should get correct identification name content from XML", () => { + const expected = <Element[]>select(xpath.coreData.identifications.identification.name.content, dom); + expect(toTextArr(coreData.identifications.identification[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct begin performance date from XML", () => { + expect(coreData.beginPerformanceDate._text).toBe(select(xpath.coreData.beginPerformanceDate, dom)); + }); + + test("should get correct end performance date from XML", () => { + expect(coreData.endPerformanceDate._text).toBe(select(xpath.coreData.endPerformanceDate, dom)); + }); + + test("should get correct performance location from XML", () => { + expect(coreData.performanceLocation._text).toBe(select(xpath.coreData.performanceLocation, dom)); + }); + + /* test for setters */ + test("should set usedLangCodeISO639_1 correctly", () => { + fc.assert( + fc.property(string_ISO639_1(), (str) => { + // add new element to array + coreData.usedLangCodeISO639_1.push(new DCCXMLElement({ _text: str })); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).toContain(str); + expect(toTextContentArr(actual)).toContain(str); + }), + ); + }); + + test("should delete usedLangCodeISO639_1 correctly", () => { + const selection = toTextContentArr(<Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom)); + fc.assert( + fc.property(fc.constantFrom(...selection), (str) => { + // get index and remove element from array + const index = indexOf(coreData.usedLangCodeISO639_1, str); + coreData.usedLangCodeISO639_1.splice(index, 1); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).not.toContain(str); + expect(toTextContentArr(actual)).not.toContain(str); + }), + ); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Customer.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Customer.test.ts new file mode 100644 index 0000000..99bc252 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Customer.test.ts @@ -0,0 +1,70 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { ContactType, DCCDocument, LocationType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:customer"; +const xpath = { + customer: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:eMail)`, + location: { + city: `${base}/dcc:location/dcc:city[1]`, + countryCode: `${base}/dcc:location/dcc:countryCode[1]`, + postCode: `${base}/dcc:location/dcc:postCode[1]`, + further: `${base}/dcc:location/dcc:further[1]/dcc:content`, + }, + descriptionData: `${base}/dcc:descriptionData`, + _id: `${base}/@id`, + }, +}; + +describe("GP_DCC_Temperature_Simplified: ContactType", () => { + let dcc: DCCDocument, customer: ContactType, location: LocationType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + customer = dcc.digitalCalibrationCertificate.administrativeData.customer; + location = customer.location; /* TODO: check iff this variable is used anywhere */ + }); + + test("should get correct customer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.customer.name.content, dom); + expect(toTextArr(customer.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct customer email address from XML", () => { + expect(customer.eMail._text).toBe(select(xpath.customer.email, dom)); + }); + + test("should get correct customer location city from XML", () => { + const expected = <Element[]>select(xpath.customer.location.city, dom); + expect(customer.location.city[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location county code from XML", () => { + const expected = <Element[]>select(xpath.customer.location.countryCode, dom); + expect(customer.location.countryCode[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location post code from XML", () => { + const expected = <Element[]>select(xpath.customer.location.postCode, dom); + expect(customer.location.postCode[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location further from XML", () => { + const expected = <Element[]>select(xpath.customer.location.further, dom); + + for (let i = 0; i < expected.length; i++) { + expect(customer.location.further[0].content[i]._text).toBe(expected[i].textContent); + } + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Items.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Items.test.ts new file mode 100644 index 0000000..66f37cf --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Items.test.ts @@ -0,0 +1,117 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { ItemType, DCCDocument, IdentificationType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:items"; +const xpath = { + items: { + item: { + name: { + content: `${base}/dcc:item[1]/dcc:name/dcc:content`, + }, + manufacturer: { + name: { + content: `${base}/dcc:item[1]/dcc:manufacturer/dcc:name/dcc:content`, + }, + }, + model: `string(${base}/dcc:item[1]/dcc:model)`, + + identifications: { + identification1: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + identification2: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:name/dcc:content`, + }, + }, + identification3: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:name/dcc:content`, + }, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Simplified: ItemType", () => { + let dcc: DCCDocument, item: ItemType, identification1, identification2, identification3: IdentificationType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + item = dcc.digitalCalibrationCertificate.administrativeData.items.item[0]; + identification1 = item.identifications.identification[0]; + identification2 = item.identifications.identification[1]; + identification3 = item.identifications.identification[2]; + }); + + test("should get correct item name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.name.content, dom); + expect(toTextArr(item.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item manufacturer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.manufacturer.name.content, dom); + expect(toTextArr(item.manufacturer.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item model from XML", () => { + expect(item.model._text).toBe(select(xpath.items.item.model, dom)); + }); + + test("should get correct identification 1 issuer from XML", () => { + expect(identification1.issuer._text).toBe(select(xpath.items.item.identifications.identification1.issuer, dom)); + }); + + test("should get correct identification 1 value from XML", () => { + expect(identification1.value._text).toBe(select(xpath.items.item.identifications.identification1.value, dom)); + }); + + test("should get correct identification 1 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification1.name.content, dom); + expect(toTextArr(identification1.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct identification 2 issuer from XML", () => { + expect(identification2.issuer._text).toBe(select(xpath.items.item.identifications.identification2.issuer, dom)); + }); + + test("should get correct identification 2 value from XML", () => { + expect(identification2.value._text).toBe(select(xpath.items.item.identifications.identification2.value, dom)); + }); + + test("should get correct identification 2 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification2.name.content, dom); + expect(toTextArr(identification2.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct identification 3 issuer from XML", () => { + expect(identification3.issuer._text).toBe(select(xpath.items.item.identifications.identification3.issuer, dom)); + }); + + test("should get correct identification 3 value from XML", () => { + expect(identification3.value._text).toBe(select(xpath.items.item.identifications.identification3.value, dom)); + }); + + test("should get correct identification 3 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification3.name.content, dom); + expect(toTextArr(identification3.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.RespPersons.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.RespPersons.test.ts new file mode 100644 index 0000000..8d52086 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.RespPersons.test.ts @@ -0,0 +1,56 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { RespPersonType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:respPersons"; +const xpath = { + respPersons: { + respPerson1: { + person: { + name: { + content: `${base}/dcc:respPerson[1]/dcc:person/dcc:name/dcc:content`, + }, + }, + mainSigner: `string(${base}/dcc:respPerson[1]/dcc:mainSigner)`, + }, + respPerson2: { + person: { + name: { + content: `${base}/dcc:respPerson[2]/dcc:person/dcc:name/dcc:content`, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Simplified: RespPersonType", () => { + let dcc: DCCDocument, respPerson1, respPerson2: RespPersonType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + respPerson1 = dcc.digitalCalibrationCertificate.administrativeData.respPersons.respPerson[0]; + respPerson2 = dcc.digitalCalibrationCertificate.administrativeData.respPersons.respPerson[1]; + }); + + test("should get correct responsible person 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.respPersons.respPerson1.person.name.content, dom); + expect(toTextArr(respPerson1.person.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct responsible person 1 main signer flag from XML", () => { + expect(respPerson1.mainSigner._text).toBe(select(xpath.respPersons.respPerson1.mainSigner, dom)); + }); + + test("should get correct responsible person 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.respPersons.respPerson2.person.name.content, dom); + expect(toTextArr(respPerson2.person.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.SoftwareListType.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.SoftwareListType.test.ts new file mode 100644 index 0000000..fb27ba6 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.SoftwareListType.test.ts @@ -0,0 +1,37 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { SoftwareListType, DCCDocument, SoftwareType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:dccSoftware/dcc:software"; +const xpath = { + software: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + release: `string(${base}/dcc:release)`, + }, +}; + +describe("GP_DCC_Temperature_Simplified: DccSoftwareType", () => { + let dcc: DCCDocument, dccSoftware: SoftwareListType, software: SoftwareType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + dccSoftware = dcc.digitalCalibrationCertificate.administrativeData.dccSoftware; + software = dccSoftware.software[0]; + }); + + test("should get correct software name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.software.name.content, dom); + expect(toTextArr(software.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct software release version of software from XML", () => { + expect(software.release._text).toBe(select(xpath.software.release, dom)); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Statements.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Statements.test.ts new file mode 100644 index 0000000..f68a629 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/AdministrativeData.Statements.test.ts @@ -0,0 +1,127 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { StatementMetaDataType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:statements"; +const xpath = { + statements: { + statement1: { + declaration: { + content: `${base}/dcc:statement[1]/dcc:declaration/dcc:content`, + }, + respAuthority: { + name: { + content: `${base}/dcc:statement[1]/dcc:respAuthority/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:statement[1]/dcc:respAuthority/dcc:eMail)`, + location: { + city: `string(${base}/dcc:statement[1]/dcc:respAuthority/dcc:location/dcc:city)`, + countryCode: `string(${base}/dcc:statement[1]/dcc:respAuthority/dcc:location/dcc:countryCode)`, + postCode: `string(${base}/dcc:statement[1]/dcc:respAuthority/dcc:location/dcc:postCode)`, + }, + }, + conformity: `string(${base}/dcc:statement[1]/dcc:conformity)`, + refType: `string(${base}/dcc:statement[1]/@refType)`, + }, + statement2: { + declaration: { + content: `${base}/dcc:statement[2]/dcc:declaration/dcc:content`, + }, + date: `string(${base}/dcc:statement[2]/dcc:date)`, + respAuthority: { + name: { + content: `${base}/dcc:statement[2]/dcc:respAuthority/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:statement[2]/dcc:respAuthority/dcc:eMail)`, + location: { + city: `string(${base}/dcc:statement[2]/dcc:respAuthority/dcc:location/dcc:city)`, + countryCode: `string(${base}/dcc:statement[2]/dcc:respAuthority/dcc:location/dcc:countryCode)`, + postCode: `string(${base}/dcc:statement[2]/dcc:respAuthority/dcc:location/dcc:postCode)`, + }, + }, + refType: `string(${base}/dcc:statement[2]/@refType)`, + }, + }, +}; + +describe("GP_DCC_Temperature_Simplified: StatementMetaDataType", () => { + let dcc: DCCDocument, statement1, statement2: StatementMetaDataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + statement1 = dcc.digitalCalibrationCertificate.administrativeData.statements.statement[0]; + statement2 = dcc.digitalCalibrationCertificate.administrativeData.statements.statement[1]; + }); + + test("should get correct statement 1 declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement1.declaration.content, dom); + expect(toTextArr(statement1.declaration.content)).toEqual(toTextContentArr(expected)); + }); + + /* responsible authority 1 */ + test("should get correct statement 1 responsible authority name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement1.respAuthority.name.content, dom); + expect(toTextArr(statement1.respAuthority.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 1 responsible authority email from XML", () => { + expect(statement1.respAuthority.eMail._text).toBe(select(xpath.statements.statement1.respAuthority.email, dom)); + }); + + test("should get correct statement 1 responsible authority location city from XML", () => { + expect(statement1.respAuthority.location.city[0]._text).toBe(select(xpath.statements.statement1.respAuthority.location.city, dom)); + }); + test("should get correct statement 1 responsible authority location country code from XML", () => { + expect(statement1.respAuthority.location.countryCode[0]._text).toBe(select(xpath.statements.statement1.respAuthority.location.countryCode, dom)); + }); + test("should get correct statement 1 responsible authority location post code from XML", () => { + expect(statement1.respAuthority.location.postCode[0]._text).toBe(select(xpath.statements.statement1.respAuthority.location.postCode, dom)); + }); + + test("should get correct statement 1 conformity from XML", () => { + expect(statement1.conformity._text).toBe(select(xpath.statements.statement1.conformity, dom)); + }); + + test("should get correct statement 2 declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement2.declaration.content, dom); + expect(toTextArr(statement2.declaration.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 2 refType from XML", () => { + expect(statement2.date._text).toBe(select(xpath.statements.statement2.date, dom)); + }); + + /* responsible authority 2 */ + test("should get correct statement 2 responsible authority name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement2.respAuthority.name.content, dom); + expect(toTextArr(statement2.respAuthority.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 2 responsible authority email from XML", () => { + expect(statement2.respAuthority.eMail._text).toBe(select(xpath.statements.statement2.respAuthority.email, dom)); + }); + + test("should get correct statement 2 responsible authority location city from XML", () => { + expect(statement2.respAuthority.location.city[0]._text).toBe(select(xpath.statements.statement2.respAuthority.location.city, dom)); + }); + test("should get correct statement 2 responsible authority location country code from XML", () => { + expect(statement2.respAuthority.location.countryCode[0]._text).toBe(select(xpath.statements.statement2.respAuthority.location.countryCode, dom)); + }); + test("should get correct statement 2 responsible authority location post code from XML", () => { + expect(statement2.respAuthority.location.postCode[0]._text).toBe(select(xpath.statements.statement2.respAuthority.location.postCode, dom)); + }); + + test("should get correct statement 2 refType from XML", () => { + expect(statement2._attr.refType).toBe(select(xpath.statements.statement2.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/DigitalCalibrationCertificateType.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/DigitalCalibrationCertificateType.test.ts new file mode 100644 index 0000000..df17932 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/DigitalCalibrationCertificateType.test.ts @@ -0,0 +1,21 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select } from "../../util"; + +const VERSION_XPATH = "string(/dcc:digitalCalibrationCertificate/@schemaVersion)"; + +describe("GP_DCC_Temperature_Simplified: DigitalCalibrationCertificateType", () => { + let xml, dcc, dom; + + beforeEach(() => { + ({ xml, dcc, dom } = xmlEnv.recreateEnv()); + }); + + test("should get correct schemaVersion from XML", () => { + const expectedVersion = select(VERSION_XPATH, dom); + expect(dcc.digitalCalibrationCertificate._attr.schemaVersion).toBe(expectedVersion); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts new file mode 100644 index 0000000..f989c1d --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts @@ -0,0 +1,218 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, InfluenceConditionListType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:influenceConditions"; +const xpath = { + measurementResults: { + measurementResult: { + influenceConditions: { + influenceCondition1: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:influenceCondition[1]/dcc:description/dcc:content`, + }, + data: { + quantity1: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[2]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[2]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:influenceCondition[1]//@refType)`, + }, + influenceCondition2: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content`, + contentDE: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content[@lang='de']`, + contentEN: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content[@lang='en']`, + }, + data: { + quantity1: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:influenceCondition[2]//@refType)`, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Simplified: InfluenceConditionListType", () => { + let dcc: DCCDocument, influenceConditions: InfluenceConditionListType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + influenceConditions = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].influenceConditions; + }); + + test("should get correct influence condition 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.description.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 quantity name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 quantity si:value from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity1.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 1 quantity si:unit from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity1.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 1 quantity 1 refType from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity1.refType, dom), + ); + }); + + test("should get correct influence condition 1 quantity 2 si:value from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[1].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity2.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 1 quantity 2 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[1].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity2.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 1 quantity 2 refType from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity2.refType, dom), + ); + }); + + test("should get correct influence condition 1 refType from XML", () => { + expect(influenceConditions.influenceCondition[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.refType, dom), + ); + }); + + test("should get correct influence condition 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.description.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 1 si:value from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 2 quantity 1 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 2 quantity 1 refType from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.refType, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].data.quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 2 si:value from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 refType from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.refType, dom), + ); + }); + + test("should get correct influence condition 2 refType from XML", () => { + expect(influenceConditions.influenceCondition[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.refType, dom), + ); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts new file mode 100644 index 0000000..d130350 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts @@ -0,0 +1,58 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, MeasuringEquipmentType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:measuringEquipments/dcc:measuringEquipment[1]"; +const xpath = { + measuringEquipments: { + measuringEquipment: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + identifications: { + identification: { + issuer: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:value)`, + }, + }, + refType: `string(${base}//@refType)`, + }, + }, +}; + +describe("GP_DCC_Temperature_Simplified: MeasuringEquipmentType", () => { + let dcc: DCCDocument, measuringEquipment: MeasuringEquipmentType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + measuringEquipment = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].measuringEquipments.measuringEquipment[0]; + }); + + test("should get correct measurement result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measuringEquipments.measuringEquipment.name.content, dom); + expect(toTextArr(measuringEquipment.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct measuring equipment 1 identification issuer from XML", () => { + expect(measuringEquipment.identifications.identification[0].issuer._text).toBe( + select(xpath.measuringEquipments.measuringEquipment.identifications.identification.issuer, dom), + ); + }); + + test("should get correct measuring equipment 1 identification value from XML", () => { + expect(measuringEquipment.identifications.identification[0].value._text).toBe( + select(xpath.measuringEquipments.measuringEquipment.identifications.identification.value, dom), + ); + }); + + test("should get correct measuring equipment 1 refType from XML", () => { + expect(measuringEquipment._attr.refType).toBe(select(xpath.measuringEquipments.measuringEquipment.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.Name.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.Name.test.ts new file mode 100644 index 0000000..6fad3df --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.Name.test.ts @@ -0,0 +1,35 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, MeasurementResultType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults"; +const xpath = { + measurementResults: { + measurementResult: { + name: { + content: `${base}/dcc:measurementResult[1]/dcc:name/dcc:content`, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Simplified: MeasurementResultType", () => { + let dcc: DCCDocument, measurementResult: MeasurementResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + measurementResult = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0]; + }); + + test("should get correct measurement result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.name.content, dom); + expect(toTextArr(measurementResult.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.Results.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.Results.test.ts new file mode 100644 index 0000000..4fd7681 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.Results.test.ts @@ -0,0 +1,339 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, ResultType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:results"; +const xpath = { + measurementResults: { + measurementResult: { + results: { + result: { + name: { + content: `${base}/dcc:result[1]/dcc:name/dcc:content`, + }, + data: { + list: { + quantity1: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]//@refType)`, + }, + quantity3: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:name/dcc:content`, + }, + si_realListXMLList: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:unitXMLList)`, + si_expandedUncXMLList: { + si_uncertaintyXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:uncertaintyXMLList)`, + si_coverageFactorXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:coverageFactorXMLList)`, + si_coverageProbabilityXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:coverageProbabilityXMLList)`, + si_distributionXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:distributionXMLList)`, + }, + }, + measurementMetaData: { + metaData: { + declaration: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData[1]/dcc:declaration/dcc:name/dcc:content`, + }, + }, + conformityXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:conformityXMLList)`, + data: { + quantity1: { + si_realListXMLList: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:realListXMLList/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:realListXMLList/si:unitXMLList)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + si_realListXMLList: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[2]/si:realListXMLList/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[2]/si:realListXMLList/si:unitXMLList)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/@refType)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]//@refType)`, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Simplified: ResultType", () => { + let dcc: DCCDocument, result: ResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + result = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].results.result[0]; + }); + + test("should get correct result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.name.content, dom); + expect(toTextArr(result.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 1 hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 1 hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 1 hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 1 hybrid si:unitXMLList 2: from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 2 hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 2 hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 2 hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 2 hybrid si:unitXMLList 2: from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 3 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[2].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 3 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 3 si:unitXMLList from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 3 uncertainty list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.uncertaintyXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_uncertaintyXMLList, dom), + ); + }); + + test("should get correct result quantity 3 uncertainty coverage factor list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.coverageFactorXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_coverageFactorXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 uncertainty coverage probability list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.coverageProbabilityXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_coverageProbabilityXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 uncertainty distribution list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.distributionXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_distributionXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 meta data declaration name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.declaration.name.content, dom) + ); + expect(toTextArr(result.data.list[0].quantity[2].measurementMetaData.metaData[0].declaration.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 3 meta data conformityXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].conformityXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.conformityXMLList, dom), + ); + }); + + test("should get correct result quantity 3 meta data quantity 1 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[0].realListXMLList.valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity1.si_realListXMLList + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 meta data quantity 1 si:unitXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[0].realListXMLList.unitXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity1.si_realListXMLList + .si_unitXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 meta data quantity 2 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[1].realListXMLList.valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity2.si_realListXMLList + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 meta data quantity 2 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[1].realListXMLList.valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity2.si_realListXMLList + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 meta data quantity 2 si:unitXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[1].realListXMLList.unitXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity2.si_realListXMLList + .si_unitXMLList, + dom, + ), + ); + }); + + test("should get correct result refType from XML", () => { + expect(result._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.refType, dom)); + }); + + test("should get correct result data list refType from XML", () => { + expect(result.data.list[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.list.refType, dom)); + }); + + test("should get correct result quantity 1 refType from XML", () => { + expect(result.data.list[0].quantity[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.refType, dom), + ); + }); + + test("should get correct result quantity2 refType from XML", () => { + expect(result.data.list[0].quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.refType, dom), + ); + }); + + test("should get correct result quantity3 refType from XML", () => { + expect(result.data.list[0].quantity[2]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.refType, dom), + ); + }); + + test("should get correct result quantity 3 meta data refType from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.refType, dom), + ); + }); + + test("should get correct result quantity 2 refType from XML", () => { + expect(result.data.list[0].quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.refType, dom), + ); + }); + + test("should get correct result quantity 3 refType from XML", () => { + expect(result.data.list[0].quantity[2]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.refType, dom), + ); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.UsedMethods.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.UsedMethods.test.ts new file mode 100644 index 0000000..6becd0f --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified/MeasurementResults.MeasurementResult.UsedMethods.test.ts @@ -0,0 +1,44 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, UsedMethodListType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]"; +const xpath = { + measurementResults: { + measurementResult: { + usedMethods: { + usedMethod1: { + name: { + content: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:name/dcc:content`, + }, + refType: `string(${base}/dcc:usedMethods/dcc:usedMethod[1]//@refType)`, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Simplified: UsedMethodListType", () => { + let dcc: DCCDocument, usedMethods: UsedMethodListType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + usedMethods = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].usedMethods; + }); + + test("should get correct used method 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.name.content, dom); + expect(toTextArr(usedMethods.usedMethod[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct used method 1 refType from XML", () => { + expect(usedMethods.usedMethod[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified_variant/AdministrativeData.Items_variant.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified_variant/AdministrativeData.Items_variant.test.ts new file mode 100644 index 0000000..de4e310 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified_variant/AdministrativeData.Items_variant.test.ts @@ -0,0 +1,37 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified_variant.xml + */ + +import { select } from "../../util"; +import { ItemType, DCCDocument, EquipmentClassType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:items"; +const xpath = { + items: { + item: { + equipmentClass: { + reference: `string(${base}/dcc:item[1]/dcc:equipmentClass[1]/dcc:reference)`, + classID: `string(${base}/dcc:item[1]/dcc:equipmentClass[1]/dcc:classID)`, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Typical: ItemType", () => { + let dcc: DCCDocument, item: ItemType, equipmentClass: EquipmentClassType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + item = dcc.digitalCalibrationCertificate.administrativeData.items.item[0]; + equipmentClass = item.equipmentClass[0]; + }); + + test("should get correct equipmentClass reference from XML", () => { + expect(equipmentClass.reference._text).toBe(select(xpath.items.item.equipmentClass.reference, dom)); + }); + + test("should get correct equipmentClass classID from XML", () => { + expect(equipmentClass.classID._text).toBe(select(xpath.items.item.equipmentClass.classID, dom)); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Simplified_variant/AdministrativeData.Statements_variant.test.ts b/tests/DCC/GP_DCC_Temperature_Simplified_variant/AdministrativeData.Statements_variant.test.ts new file mode 100644 index 0000000..26ad9a3 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Simplified_variant/AdministrativeData.Statements_variant.test.ts @@ -0,0 +1,95 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Simplified_variant.xml + */ + +import * as fc from "fast-check"; +import { select, toTextArr, toTextContentArr, indexOf } from "../../util"; +import { StatementMetaDataType, DCCDocument, DCCXMLElement } from "../../../src"; +import { string_ISO3166_1 } from "../../Arbitraries"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:statements"; +const xpath = { + statements: { + statement3: { + countryCodeISO3166_1: `${base}/dcc:statement[3]/dcc:countryCodeISO3166_1`, + convention: `string(${base}/dcc:statement[3]/dcc:convention)`, + traceable: `string(${base}/dcc:statement[3]/dcc:traceable)`, + period: `string(${base}/dcc:statement[3]/dcc:period)`, + nonSIDefinition: `string(${base}/dcc:statement[3]/dcc:nonSIDefinition)`, + nonSIUnit: `string(${base}/dcc:statement[3]/dcc:nonSIUnit)`, + }, + }, +}; + +describe("GP_DCC_Temperature_Simplified: StatementMetaDataType", () => { + let dcc: DCCDocument, statement3: StatementMetaDataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + statement3 = dcc.digitalCalibrationCertificate.administrativeData.statements.statement[2]; + }); + + test("should get correct statement 3 countryCodeISO3166_1 from XML", () => { + const expected = <Element[]>select(xpath.statements.statement3.countryCodeISO3166_1, dom); + expect(toTextArr(statement3.countryCodeISO3166_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 3 convention from XML", () => { + const expected = select(xpath.statements.statement3.convention, dom); + expect(statement3.convention._text).toEqual(expected); + }); + + test("should get correct statement 3 traceable from XML", () => { + const expected = select(xpath.statements.statement3.traceable, dom); + expect(statement3.traceable._text).toEqual(expected); + }); + + test("should get correct statement 3 period from XML", () => { + const expected = select(xpath.statements.statement3.period, dom); + expect(statement3.period._text).toEqual(expected); + }); + + test("should get correct statement 3 nonSIDefinition from XML", () => { + const expected = select(xpath.statements.statement3.nonSIDefinition, dom); + expect(statement3.nonSIDefinition._text).toEqual(expected); + }); + + test("should get correct statement 3 nonSIUnit from XML", () => { + const expected = select(xpath.statements.statement3.nonSIUnit, dom); + expect(statement3.nonSIUnit._text).toEqual(expected); + }); + + /* test for setters */ + test("should set statement 3 countryCodeISO3166_1 correctly", () => { + fc.assert( + fc.property(string_ISO3166_1(), (str) => { + // add new element to array + statement3.countryCodeISO3166_1.push(new DCCXMLElement({ _text: str })); + + // get actual list from xml + const actual = <Element[]>select(xpath.statements.statement3.countryCodeISO3166_1, dcc); + + expect(toTextArr(statement3.countryCodeISO3166_1)).toContain(str); + expect(toTextContentArr(actual)).toContain(str); + }), + ); + }); + + test("should delete statement 3 countryCodeISO3166_1 correctly", () => { + const selection = toTextContentArr(<Element[]>select(xpath.statements.statement3.countryCodeISO3166_1, dom)); + fc.assert( + fc.property(fc.constantFrom(...selection), (str) => { + // get index and remove element from array + const index = indexOf(statement3.countryCodeISO3166_1, str); + statement3.countryCodeISO3166_1.splice(index, 1); + + // get actual list from xml + const actual = <Element[]>select(xpath.statements.statement3.countryCodeISO3166_1, dcc); + + expect(toTextArr(statement3.countryCodeISO3166_1)).not.toContain(str); + expect(toTextContentArr(actual)).not.toContain(str); + }), + ); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.CalibrationLaboratory.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.CalibrationLaboratory.test.ts new file mode 100644 index 0000000..fdaf96a --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.CalibrationLaboratory.test.ts @@ -0,0 +1,80 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { CalibrationLaboratoryType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:calibrationLaboratory/dcc:contact"; +const xpath = { + name: `string(${base}/dcc:name/dcc:content)`, + eMail: `string(${base}/dcc:eMail)`, + phone: `string(${base}/dcc:phone)`, + fax: `string(${base}/dcc:fax)`, + location: { + city: `${base}/dcc:location/dcc:city`, + countryCode: `${base}/dcc:location/dcc:countryCode`, + postCode: `${base}/dcc:location/dcc:postCode`, + street: `${base}/dcc:location/dcc:street`, + streetNo: `${base}/dcc:location/dcc:streetNo`, + further: `${base}/dcc:location/dcc:further/dcc:content`, + }, +}; + +describe("GP_DCC_Temperature_Typical: CalibrationLaboratoryType", () => { + let dcc: DCCDocument, calibrationLaboratory: CalibrationLaboratoryType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + calibrationLaboratory = dcc.digitalCalibrationCertificate.administrativeData.calibrationLaboratory; + }); + + test("should get correct name from XML", () => { + expect(calibrationLaboratory.contact.name.content[0]._text).toBe(select(xpath.name, dom)); + }); + + test("should get correct eMail from XML", () => { + expect(calibrationLaboratory.contact.eMail._text).toBe(select(xpath.eMail, dom)); + }); + + test("should get correct phone from XML", () => { + expect(calibrationLaboratory.contact.phone._text).toBe(select(xpath.phone, dom)); + }); + + test("should get correct city from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.city, dom); + expect(toTextArr(calibrationLaboratory.contact.location.city)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct countryCode from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.countryCode, dom); + expect(toTextArr(calibrationLaboratory.contact.location.countryCode)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct postCode from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.postCode, dom); + expect(toTextArr(calibrationLaboratory.contact.location.postCode)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct street from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.street, dom); + expect(toTextArr(calibrationLaboratory.contact.location.street)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct streetNo from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.streetNo, dom); + expect(toTextArr(calibrationLaboratory.contact.location.streetNo)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct further element from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.further, dom); + expect(toTextArr(calibrationLaboratory.contact.location.further[0].content)).toEqual(toTextContentArr(expected)); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.CoreDataType.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.CoreDataType.test.ts new file mode 100644 index 0000000..da8c8ee --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.CoreDataType.test.ts @@ -0,0 +1,120 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import * as fc from "fast-check"; +import { indexOf, select, toTextArr, toTextContentArr } from "../../util"; +import { CoreDataType, DCCDocument, DCCXMLElement } from "../../../src"; +import { string_ISO639_1 } from "../../Arbitraries"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:coreData"; +const xpath = { + coreData: { + countryCodeISO3166_1: `string(${base}/dcc:countryCodeISO3166_1)`, + usedLangCodeISO639_1: `${base}/dcc:usedLangCodeISO639_1`, + mandatoryLangCodeISO639_1: `${base}/dcc:mandatoryLangCodeISO639_1`, + uniqueIdentifier: `string(${base}/dcc:uniqueIdentifier)`, + identifications: { + identification: { + issuer: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + }, + receiptDate: `string(${base}/dcc:receiptDate)`, + beginPerformanceDate: `string(${base}/dcc:beginPerformanceDate)`, + endPerformanceDate: `string(${base}/dcc:endPerformanceDate)`, + performanceLocation: `string(${base}/dcc:performanceLocation)`, + }, +}; + +describe("GP_DCC_Temperature_Typical: CoreDataType", () => { + let dcc: DCCDocument, coreData: CoreDataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + coreData = dcc.digitalCalibrationCertificate.administrativeData.coreData; + }); + + test("should get correct countryCodeISO3166_1 from XML", () => { + expect(coreData.countryCodeISO3166_1._text).toBe(select(xpath.coreData.countryCodeISO3166_1, dom)); + }); + + test("should get correct usedLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom); + expect(toTextArr(coreData.usedLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct mandatoryLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.mandatoryLangCodeISO639_1, dom); + expect(toTextArr(coreData.mandatoryLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct unique identifier from XML", () => { + expect(coreData.uniqueIdentifier._text).toBe(select(xpath.coreData.uniqueIdentifier, dom)); + }); + + test("should get correct identification issuer from XML", () => { + expect(coreData.identifications.identification[0].issuer._text).toBe(select(xpath.coreData.identifications.identification.issuer, dom)); + }); + + test("should get correct identification value from XML", () => { + expect(coreData.identifications.identification[0].value._text).toBe(select(xpath.coreData.identifications.identification.value, dom)); + }); + + test("should get correct identification name content from XML", () => { + const expected = <Element[]>select(xpath.coreData.identifications.identification.name.content, dom); + expect(toTextArr(coreData.identifications.identification[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct receipt date from XML", () => { + expect(coreData.receiptDate._text).toBe(select(xpath.coreData.receiptDate, dom)); + }); + test("should get correct begin performance date from XML", () => { + expect(coreData.beginPerformanceDate._text).toBe(select(xpath.coreData.beginPerformanceDate, dom)); + }); + test("should get correct end performance date from XML", () => { + expect(coreData.endPerformanceDate._text).toBe(select(xpath.coreData.endPerformanceDate, dom)); + }); + test("should get correct performance location from XML", () => { + expect(coreData.performanceLocation._text).toBe(select(xpath.coreData.performanceLocation, dom)); + }); + + /* test for setters */ + test("should set usedLangCodeISO639_1 correctly", () => { + fc.assert( + fc.property(string_ISO639_1(), (str) => { + // add new element to array + coreData.usedLangCodeISO639_1.push(new DCCXMLElement({ _text: str })); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).toContain(str); + expect(toTextContentArr(actual)).toContain(str); + }), + ); + }); + + test("should delete usedLangCodeISO639_1 correctly", () => { + const selection = toTextContentArr(<Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom)); + fc.assert( + fc.property(fc.constantFrom(...selection), (str) => { + // get index and remove element from array + const index = indexOf(coreData.usedLangCodeISO639_1, str); + coreData.usedLangCodeISO639_1.splice(index, 1); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).not.toContain(str); + expect(toTextContentArr(actual)).not.toContain(str); + }), + ); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Customer.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Customer.test.ts new file mode 100644 index 0000000..e03dd5c --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Customer.test.ts @@ -0,0 +1,77 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { ContactType, DCCDocument, LocationType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:customer"; +const xpath = { + customer: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:eMail)`, + phone: `string(${base}/dcc:phone)`, + fax: `string(${base}/dcc:fax)`, + location: { + city: `${base}/dcc:location/dcc:city[1]`, + countryCode: `${base}/dcc:location/dcc:countryCode[1]`, + postCode: `${base}/dcc:location/dcc:postCode[1]`, + postBoxOffice: `${base}/dcc:location/dcc:postBoxOffice[1]`, + state: `${base}/dcc:location/dcc:state[1]`, + street: `${base}/dcc:location/dcc:street[1]`, + streetNo: `${base}/dcc:location/dcc:streetNo[1]`, + further: `${base}/dcc:location/dcc:further[1]/dcc:content`, + positionCoordinates: `${base}/dcc:location/dcc:positionCoordinates[1]`, + }, + descriptionData: `${base}/dcc:descriptionData`, + _id: `${base}/@id`, + }, +}; + +describe("GP_DCC_Temperature_Typical: ContactType", () => { + let dcc: DCCDocument, customer: ContactType, location: LocationType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + customer = dcc.digitalCalibrationCertificate.administrativeData.customer; + location = customer.location; /* TODO: check iff this variable is used anywhere */ + }); + + test("should get correct customer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.customer.name.content, dom); + expect(toTextArr(customer.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct customer email address from XML", () => { + expect(customer.eMail._text).toBe(select(xpath.customer.email, dom)); + }); + + test("should get correct customer location city from XML", () => { + const expected = <Element[]>select(xpath.customer.location.city, dom); + expect(customer.location.city[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location county code from XML", () => { + const expected = <Element[]>select(xpath.customer.location.countryCode, dom); + expect(customer.location.countryCode[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location post code from XML", () => { + const expected = <Element[]>select(xpath.customer.location.postCode, dom); + expect(customer.location.postCode[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location further from XML", () => { + const expected = <Element[]>select(xpath.customer.location.further, dom); + + for (let i = 0; i < expected.length; i++) { + expect(customer.location.further[0].content[i]._text).toBe(expected[i].textContent); + } + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Items.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Items.test.ts new file mode 100644 index 0000000..dce1bac --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Items.test.ts @@ -0,0 +1,117 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { ItemType, DCCDocument, IdentificationType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:items"; +const xpath = { + items: { + item: { + name: { + content: `${base}/dcc:item[1]/dcc:name/dcc:content`, + }, + manufacturer: { + name: { + content: `${base}/dcc:item[1]/dcc:manufacturer/dcc:name/dcc:content`, + }, + }, + model: `string(${base}/dcc:item[1]/dcc:model)`, + + identifications: { + identification1: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + identification2: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:name/dcc:content`, + }, + }, + identification3: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:name/dcc:content`, + }, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Typical: ItemType", () => { + let dcc: DCCDocument, item: ItemType, identification1, identification2, identification3: IdentificationType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + item = dcc.digitalCalibrationCertificate.administrativeData.items.item[0]; + identification1 = item.identifications.identification[0]; + identification2 = item.identifications.identification[1]; + identification3 = item.identifications.identification[2]; + }); + + test("should get correct item name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.name.content, dom); + expect(toTextArr(item.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item manufacturer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.manufacturer.name.content, dom); + expect(toTextArr(item.manufacturer.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item model from XML", () => { + expect(item.model._text).toBe(select(xpath.items.item.model, dom)); + }); + + test("should get correct identification 1 issuer from XML", () => { + expect(identification1.issuer._text).toBe(select(xpath.items.item.identifications.identification1.issuer, dom)); + }); + + test("should get correct identification 1 value from XML", () => { + expect(identification1.value._text).toBe(select(xpath.items.item.identifications.identification1.value, dom)); + }); + + test("should get correct identification 1 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification1.name.content, dom); + expect(toTextArr(identification1.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct identification 2 issuer from XML", () => { + expect(identification2.issuer._text).toBe(select(xpath.items.item.identifications.identification2.issuer, dom)); + }); + + test("should get correct identification 2 value from XML", () => { + expect(identification2.value._text).toBe(select(xpath.items.item.identifications.identification2.value, dom)); + }); + + test("should get correct identification 2 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification2.name.content, dom); + expect(toTextArr(identification2.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct identification 3 issuer from XML", () => { + expect(identification3.issuer._text).toBe(select(xpath.items.item.identifications.identification3.issuer, dom)); + }); + + test("should get correct identification 3 value from XML", () => { + expect(identification3.value._text).toBe(select(xpath.items.item.identifications.identification3.value, dom)); + }); + + test("should get correct identification 3 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification3.name.content, dom); + expect(toTextArr(identification3.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.RespPersons.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.RespPersons.test.ts new file mode 100644 index 0000000..583b3f8 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.RespPersons.test.ts @@ -0,0 +1,56 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { RespPersonType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:respPersons"; +const xpath = { + respPersons: { + respPerson1: { + person: { + name: { + content: `${base}/dcc:respPerson[1]/dcc:person/dcc:name/dcc:content`, + }, + }, + mainSigner: `string(${base}/dcc:respPerson[1]/dcc:mainSigner)`, + }, + respPerson2: { + person: { + name: { + content: `${base}/dcc:respPerson[2]/dcc:person/dcc:name/dcc:content`, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Typical: RespPersonType", () => { + let dcc: DCCDocument, respPerson1, respPerson2: RespPersonType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + respPerson1 = dcc.digitalCalibrationCertificate.administrativeData.respPersons.respPerson[0]; + respPerson2 = dcc.digitalCalibrationCertificate.administrativeData.respPersons.respPerson[1]; + }); + + test("should get correct responsible person 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.respPersons.respPerson1.person.name.content, dom); + expect(toTextArr(respPerson1.person.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct responsible person 1 main signer flag from XML", () => { + expect(respPerson1.mainSigner._text).toBe(select(xpath.respPersons.respPerson1.mainSigner, dom)); + }); + + test("should get correct responsible person 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.respPersons.respPerson2.person.name.content, dom); + expect(toTextArr(respPerson2.person.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.SoftwareListType.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.SoftwareListType.test.ts new file mode 100644 index 0000000..cb02695 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.SoftwareListType.test.ts @@ -0,0 +1,39 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { SoftwareListType, DCCDocument, SoftwareType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:dccSoftware/dcc:software"; +const xpath = { + software: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + release: `string(${base}/dcc:release)`, + _id: `${base}/@id`, + _refType: `${base}/@refType`, + }, +}; + +describe("GP_DCC_Temperature_Typical: DccSoftwareType", () => { + let dcc: DCCDocument, dccSoftware: SoftwareListType, software: SoftwareType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + dccSoftware = dcc.digitalCalibrationCertificate.administrativeData.dccSoftware; + software = dccSoftware.software[0]; + }); + + test("should get correct software name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.software.name.content, dom); + expect(toTextArr(software.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct software release version of software from XML", () => { + expect(software.release._text).toBe(select(xpath.software.release, dom)); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Statements.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Statements.test.ts new file mode 100644 index 0000000..0c5ae36 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/AdministrativeData.Statements.test.ts @@ -0,0 +1,213 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { StatementMetaDataType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:statements"; +const xpath = { + statements: { + statement1: { + norm: `string(${base}/dcc:statement[1]/dcc:norm)`, + reference: `string(${base}/dcc:statement[1]/dcc:reference)`, + declaration: { + content: `${base}/dcc:statement[1]/dcc:declaration/dcc:content`, + }, + refType: `string(${base}/dcc:statement[1]/@refType)`, + }, + statement2: { + declaration: { + content: `${base}/dcc:statement[2]/dcc:declaration/dcc:content`, + }, + data: { + quantity1: { + name: { + content: `${base}/dcc:statement[2]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:statement[2]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:statement[2]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + }, + quantity2: { + name: { + content: `${base}/dcc:statement[2]/dcc:data/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:statement[2]/dcc:data/dcc:quantity[2]/si:real/si:value)`, + si_unit: `string(${base}/dcc:statement[2]/dcc:data/dcc:quantity[2]/si:real/si:unit)`, + }, + }, + }, + refType: `string(${base}/dcc:statement[2]/@refType)`, + }, + statement3: { + declaration: { + content: `${base}/dcc:statement[3]/dcc:declaration/dcc:content`, + }, + respAuthority: { + name: { + content: `${base}/dcc:statement[3]/dcc:respAuthority/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:statement[3]/dcc:respAuthority/dcc:email)`, + location: { + city: `string(${base}/dcc:statement[3]/dcc:respAuthority/dcc:location/dcc:city)`, + countryCode: `string(${base}/dcc:statement[3]/dcc:respAuthority/dcc:location/dcc:countryCode)`, + postCode: `string(${base}/dcc:statement[3]/dcc:respAuthority/dcc:location/dcc:postCode)`, + }, + }, + conformity: `string(${base}/dcc:statement[3]/dcc:conformity)`, + refType: `string(${base}/dcc:statement[3]/@refType)`, + }, + statement4: { + declaration: { + content: `${base}/dcc:statement[4]/dcc:declaration/dcc:content`, + }, + date: `string(${base}/dcc:statement[4]/dcc:date)`, + respAuthority: { + name: { + content: `${base}/dcc:statement[3]/dcc:respAuthority/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:statement[3]/dcc:respAuthority/dcc:email)`, + location: { + city: `string(${base}/dcc:statement[3]/dcc:respAuthority/dcc:location/dcc:city)`, + countryCode: `string(${base}/dcc:statement[3]/dcc:respAuthority/dcc:location/dcc:countryCode)`, + postCode: `string(${base}/dcc:statement[3]/dcc:respAuthority/dcc:location/dcc:postCode)`, + }, + }, + refType: `string(${base}/dcc:statement[4]/@refType)`, + }, + }, +}; + +describe("GP_DCC_Temperature_Typical: StatementMetaDataType", () => { + let dcc: DCCDocument, statement1, statement2, statement3, statement4: StatementMetaDataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + statement1 = dcc.digitalCalibrationCertificate.administrativeData.statements.statement[0]; + statement2 = dcc.digitalCalibrationCertificate.administrativeData.statements.statement[1]; + statement3 = dcc.digitalCalibrationCertificate.administrativeData.statements.statement[2]; + statement4 = dcc.digitalCalibrationCertificate.administrativeData.statements.statement[3]; + }); + + test("should get correct statement 1 declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement1.declaration.content, dom); + expect(toTextArr(statement1.declaration.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 1 norm model from XML", () => { + expect(statement1.norm[0]._text).toBe(select(xpath.statements.statement1.norm, dom)); + }); + + test("should get correct statement 1 reference from XML", () => { + expect(statement1.reference[0]._text).toBe(select(xpath.statements.statement1.reference, dom)); + }); + + test("should get correct statement 2 declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement2.declaration.content, dom); + expect(toTextArr(statement2.declaration.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 2 data quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement2.data.quantity1.name.content, dom); + expect(toTextArr(statement2.data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 2 data quantity 1 si:value from XML", () => { + expect(statement2.data.quantity[0].real.value._text).toBe(select(xpath.statements.statement2.data.quantity1.si_real.si_value, dom)); + }); + + test("should get correct statement 2 data quantity 2 si:unit from XML", () => { + expect(statement2.data.quantity[0].real.unit._text).toBe(select(xpath.statements.statement2.data.quantity1.si_real.si_unit, dom)); + }); + + test("should get correct statement 2 data quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement2.data.quantity2.name.content, dom); + expect(toTextArr(statement2.data.quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 2 data quantity 2 si:value from XML", () => { + expect(statement2.data.quantity[1].real.value._text).toBe(select(xpath.statements.statement2.data.quantity2.si_real.si_value, dom)); + }); + + test("should get correct statement 2 data quantity 2 si:unit from XML", () => { + expect(statement2.data.quantity[1].real.unit._text).toBe(select(xpath.statements.statement2.data.quantity2.si_real.si_unit, dom)); + }); + + test("should get correct statement 2 refType from XML", () => { + expect(statement2._attr.refType).toBe(select(xpath.statements.statement2.refType, dom)); + }); + + test("should get correct statement 3 declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement3.declaration.content, dom); + expect(toTextArr(statement3.declaration.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 3 responsible authority name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement3.respAuthority.name.content, dom); + expect(toTextArr(statement3.respAuthority.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* responsible authority 3 */ + test("should get correct statement 3 responsible authority email from XML", () => { + expect(statement3.respAuthority.eMail._text).toBe(select(xpath.statements.statement3.respAuthority.email, dom)); + }); + + test("should get correct statement 3 responsible authority location city from XML", () => { + expect(statement3.respAuthority.location.city[0]._text).toBe(select(xpath.statements.statement3.respAuthority.location.city, dom)); + }); + test("should get correct statement 3 responsible authority location country code from XML", () => { + expect(statement3.respAuthority.location.countryCode[0]._text).toBe(select(xpath.statements.statement3.respAuthority.location.countryCode, dom)); + }); + test("should get correct statement 3 responsible authority location post code from XML", () => { + expect(statement3.respAuthority.location.postCode[0]._text).toBe(select(xpath.statements.statement3.respAuthority.location.postCode, dom)); + }); + + test("should get correct statement 3 conformity from XML", () => { + expect(statement3.conformity._text).toBe(select(xpath.statements.statement3.conformity, dom)); + }); + + test("should get correct statement 3 refType from XML", () => { + expect(statement3._attr.refType).toBe(select(xpath.statements.statement3.refType, dom)); + }); + + test("should get correct statement 4 declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement4.declaration.content, dom); + expect(toTextArr(statement4.declaration.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 4 date from XML", () => { + expect(statement4.date._text).toBe(select(xpath.statements.statement4.date, dom)); + }); + + /* responsible authority 4 */ + test("should get correct statement 4 responsible authority email from XML", () => { + expect(statement4.respAuthority.eMail._text).toBe(select(xpath.statements.statement4.respAuthority.email, dom)); + }); + + test("should get correct statement 4 responsible authority location city from XML", () => { + expect(statement4.respAuthority.location.city[0]._text).toBe(select(xpath.statements.statement4.respAuthority.location.city, dom)); + }); + test("should get correct statement 4 responsible authority location country code from XML", () => { + expect(statement4.respAuthority.location.countryCode[0]._text).toBe(select(xpath.statements.statement4.respAuthority.location.countryCode, dom)); + }); + test("should get correct statement 4 responsible authority location post code from XML", () => { + expect(statement4.respAuthority.location.postCode[0]._text).toBe(select(xpath.statements.statement4.respAuthority.location.postCode, dom)); + }); + + test("should get correct statement 4 refType from XML", () => { + expect(statement4._attr.refType).toBe(select(xpath.statements.statement4.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/DigitalCalibrationCertificateType.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/DigitalCalibrationCertificateType.test.ts new file mode 100644 index 0000000..110f096 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/DigitalCalibrationCertificateType.test.ts @@ -0,0 +1,21 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select } from "../../util"; + +const VERSION_XPATH = "string(/dcc:digitalCalibrationCertificate/@schemaVersion)"; + +describe("GP_DCC_Temperature_Typical: DigitalCalibrationCertificateType", () => { + let xml, dcc, dom; + + beforeEach(() => { + ({ xml, dcc, dom } = xmlEnv.recreateEnv()); + }); + + test("should get correct schemaVersion from XML", () => { + const expectedVersion = select(VERSION_XPATH, dom); + expect(dcc.digitalCalibrationCertificate._attr.schemaVersion).toBe(expectedVersion); + }); +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts new file mode 100644 index 0000000..436f8d3 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts @@ -0,0 +1,249 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, InfluenceConditionListType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:influenceConditions"; +const xpath = { + measurementResults: { + measurementResult: { + influenceConditions: { + influenceCondition1: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:name/dcc:content`, + }, + data: { + quantity: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + }, + }, + refType: `string(${base}/dcc:influenceCondition[1]//@refType)`, + }, + influenceCondition2: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content`, + contentDE: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content[@lang='de']`, + contentEN: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content[@lang='en']`, + }, + data: { + quantity1: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:influenceCondition[2]//@refType)`, + }, + influenceCondition3: { + name: { + content: `${base}/dcc:influenceCondition[3]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:influenceCondition[3]/dcc:description/dcc:content`, + contentDE: `${base}/dcc:influenceCondition[3]/dcc:description/dcc:content[@lang='de']`, + contentEN: `${base}/dcc:influenceCondition[3]/dcc:description/dcc:content[@lang='en']`, + }, + data: { + quantity1: { + name: { + content: `${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[2]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[2]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:influenceCondition[3]//@refType)`, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Typical: InfluenceConditionListType", () => { + let dcc: DCCDocument, influenceConditions: InfluenceConditionListType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + influenceConditions = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].influenceConditions; + }); + + test("should get correct influence condition 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 quantity name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 quantity si:value from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 1 quantity si:unit from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 1 refType from XML", () => { + expect(influenceConditions.influenceCondition[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.refType, dom), + ); + }); + + test("should get correct influence condition 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.description.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 1 si:value from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 2 quantity 1 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].data.quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 2 si:value from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 2 refType from XML", () => { + expect(influenceConditions.influenceCondition[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.refType, dom), + ); + }); + + test("should get correct influence condition 3 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[2].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 3 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.description.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[2].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 3 quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[2].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 3 quantity 1 si:value from XML", () => { + expect(influenceConditions.influenceCondition[2].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity1.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 3 quantity 1 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[2].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity1.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 3 quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[2].data.quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 3 quantity 2 si:value from XML", () => { + expect(influenceConditions.influenceCondition[2].data.quantity[1].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity2.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 3 quantity 2 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[2].data.quantity[1].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity2.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 3 refType from XML", () => { + expect(influenceConditions.influenceCondition[2]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.refType, dom), + ); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts new file mode 100644 index 0000000..856134e --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts @@ -0,0 +1,58 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, MeasuringEquipmentType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:measuringEquipments/dcc:measuringEquipment[1]"; +const xpath = { + measuringEquipments: { + measuringEquipment: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + identifications: { + identification: { + issuer: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:value)`, + }, + }, + refType: `string(${base}//@refType)`, + }, + }, +}; + +describe("GP_DCC_Temperature_Typical: MeasuringEquipmentType", () => { + let dcc: DCCDocument, measuringEquipment: MeasuringEquipmentType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + measuringEquipment = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].measuringEquipments.measuringEquipment[0]; + }); + + test("should get correct measurement result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measuringEquipments.measuringEquipment.name.content, dom); + expect(toTextArr(measuringEquipment.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct measuring equipment 1 identification issuer from XML", () => { + expect(measuringEquipment.identifications.identification[0].issuer._text).toBe( + select(xpath.measuringEquipments.measuringEquipment.identifications.identification.issuer, dom), + ); + }); + + test("should get correct measuring equipment 1 identification value from XML", () => { + expect(measuringEquipment.identifications.identification[0].value._text).toBe( + select(xpath.measuringEquipments.measuringEquipment.identifications.identification.value, dom), + ); + }); + + test("should get correct measuring equipment 1 refType from XML", () => { + expect(measuringEquipment._attr.refType).toBe(select(xpath.measuringEquipments.measuringEquipment.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.Name.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.Name.test.ts new file mode 100644 index 0000000..892a1f3 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.Name.test.ts @@ -0,0 +1,35 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, MeasurementResultType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults"; +const xpath = { + measurementResults: { + measurementResult: { + name: { + content: `${base}/dcc:measurementResult[1]/dcc:name/dcc:content`, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Typical: MeasurementResultType", () => { + let dcc: DCCDocument, measurementResult: MeasurementResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + measurementResult = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0]; + }); + + test("should get correct measurement result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.name.content, dom); + expect(toTextArr(measurementResult.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.Results.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.Results.test.ts new file mode 100644 index 0000000..9efe9ae --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.Results.test.ts @@ -0,0 +1,302 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, ResultType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:results"; +const xpath = { + measurementResults: { + measurementResult: { + results: { + result: { + name: { + content: `${base}/dcc:result[1]/dcc:name/dcc:content`, + }, + data: { + list: { + quantity1: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + measurementMetaData: { + metaData: { + declaration: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:declaration/dcc:content`, + }, + data: { + quantity: { + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]//@refType)`, + }, + quantity3: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:name/dcc:content`, + }, + si_realListXMLList: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:unitXMLList)`, + si_expandedUncXMLList: { + si_uncertaintyXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:uncertaintyXMLList)`, + si_coverageFactorXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:coverageFactorXMLList)`, + si_coverageProbabilityXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:coverageProbabilityXMLList)`, + si_distributionXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:distributionXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/@refType)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]//@refType)`, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Typical: ResultType", () => { + let dcc: DCCDocument, result: ResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + result = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].results.result[0]; + }); + + test("should get correct result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.name.content, dom); + expect(toTextArr(result.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 1 hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 1 hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 1 hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 1 hybrid si:unitXMLList 2: from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 1 meta data declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.declaration.content, dom) + ); + expect(toTextArr(result.data.list[0].quantity[0].measurementMetaData.metaData[0].declaration.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 1 meta data hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0].data.quantity[0].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.data.quantity.si_hybrid.si_realListXMLList1 + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 1 meta data hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0].data.quantity[0].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.data.quantity.si_hybrid.si_realListXMLList1 + .si_unitXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 1 meta data hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0].data.quantity[0].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.data.quantity.si_hybrid.si_realListXMLList2 + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 1 meta data hybrid si:unitXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0].data.quantity[0].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 2 hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 2 hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 2 hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 2 hybrid si:unitXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 3 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[2].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 3 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 3 si:unitXMLList from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 3 uncertainty list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.uncertaintyXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_uncertaintyXMLList, dom), + ); + }); + + test("should get correct result quantity 3 uncertainty coverage factor list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.coverageFactorXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_coverageFactorXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 uncertainty coverage probability list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.coverageProbabilityXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_coverageProbabilityXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 uncertainty distribution list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.distributionXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_distributionXMLList, + dom, + ), + ); + }); + + test("should get correct result refType from XML", () => { + expect(result._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.refType, dom)); + }); + + test("should get correct result data list refType from XML", () => { + expect(result.data.list[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.list.refType, dom)); + }); + + test("should get correct result quantity 1 refType from XML", () => { + expect(result.data.list[0].quantity[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.refType, dom), + ); + }); + + test("should get correct result quantity 1 meta data refType from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.refType, dom), + ); + }); + + test("should get correct result quantity 2 refType from XML", () => { + expect(result.data.list[0].quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.refType, dom), + ); + }); + + test("should get correct result quantity 3 refType from XML", () => { + expect(result.data.list[0].quantity[2]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.refType, dom), + ); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.UsedMethods.test.ts b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.UsedMethods.test.ts new file mode 100644 index 0000000..4738344 --- /dev/null +++ b/tests/DCC/GP_DCC_Temperature_Typical/MeasurementResults.MeasurementResult.UsedMethods.test.ts @@ -0,0 +1,81 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_Typical.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, UsedMethodListType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]"; +const xpath = { + measurementResults: { + measurementResult: { + usedMethods: { + usedMethod1: { + name: { + content: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:description/dcc:content`, + contentDE: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:description/dcc:content[@lang='de']`, + contentEN: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:description/dcc:content[@lang='en']`, + }, + norm: `string(${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:norm[1])`, + refType: `string(${base}/dcc:usedMethods/dcc:usedMethod[1]//@refType)`, + }, + usedMethod2: { + name: { + content: `${base}/dcc:usedMethods/dcc:usedMethod[2]/dcc:name/dcc:content`, + }, + norm: `string(${base}/dcc:usedMethods/dcc:usedMethod[2]/dcc:norm[1])`, + refType: `string(${base}/dcc:usedMethods/dcc:usedMethod[2]//@refType)`, + }, + }, + }, + }, +}; + +describe("GP_DCC_Temperature_Typical: UsedMethodListType", () => { + let dcc: DCCDocument, usedMethods: UsedMethodListType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + usedMethods = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].usedMethods; + }); + + test("should get correct used method 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.name.content, dom); + expect(toTextArr(usedMethods.usedMethod[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct used method 1 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.description.content, dom); + expect(toTextArr(usedMethods.usedMethod[0].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct used method 1 norm from XML", () => { + expect(usedMethods.usedMethod[0].norm[0]._text).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.norm, dom)); + }); + + test("should get correct used method 1 refType from XML", () => { + expect(usedMethods.usedMethod[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.refType, dom)); + }); + + test("should get correct used method 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.usedMethods.usedMethod2.name.content, dom); + expect(toTextArr(usedMethods.usedMethod[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct used method 2 norm from XML", () => { + expect(usedMethods.usedMethod[1].norm[0]._text).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod2.norm, dom)); + }); + + test("should get correct used method 2 refType from XML", () => { + expect(usedMethods.usedMethod[1]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod2.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.CalibrationLaboratory.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.CalibrationLaboratory.test.ts new file mode 100644 index 0000000..9372426 --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.CalibrationLaboratory.test.ts @@ -0,0 +1,84 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { CalibrationLaboratoryType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:calibrationLaboratory/dcc:contact"; +const xpath = { + name: `string(${base}/dcc:name/dcc:content)`, + eMail: `string(${base}/dcc:eMail)`, + phone: `string(${base}/dcc:phone)`, + fax: `string(${base}/dcc:fax)`, + location: { + city: `${base}/dcc:location/dcc:city`, + countryCode: `${base}/dcc:location/dcc:countryCode`, + postCode: `${base}/dcc:location/dcc:postCode`, + street: `${base}/dcc:location/dcc:street`, + streetNo: `${base}/dcc:location/dcc:streetNo`, + further: `${base}/dcc:location/dcc:further/dcc:content`, + }, +}; + +describe("GP_Temperature_Complete_DCC: CalibrationLaboratoryType", () => { + let dcc: DCCDocument, calibrationLaboratory: CalibrationLaboratoryType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + calibrationLaboratory = dcc.digitalCalibrationCertificate.administrativeData.calibrationLaboratory; + }); + + test("should get correct name from XML", () => { + expect(calibrationLaboratory.contact.name.content[0]._text).toBe(select(xpath.name, dom)); + }); + + test("should get correct eMail from XML", () => { + expect(calibrationLaboratory.contact.eMail._text).toBe(select(xpath.eMail, dom)); + }); + + test("should get correct phone from XML", () => { + expect(calibrationLaboratory.contact.phone._text).toBe(select(xpath.phone, dom)); + }); + + test("should get correct fax from XML", () => { + expect(calibrationLaboratory.contact.fax._text).toBe(select(xpath.fax, dom)); + }); + + test("should get correct city from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.city, dom); + expect(toTextArr(calibrationLaboratory.contact.location.city)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct countryCode from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.countryCode, dom); + expect(toTextArr(calibrationLaboratory.contact.location.countryCode)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct postCode from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.postCode, dom); + expect(toTextArr(calibrationLaboratory.contact.location.postCode)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct street from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.street, dom); + expect(toTextArr(calibrationLaboratory.contact.location.street)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct streetNo from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.streetNo, dom); + expect(toTextArr(calibrationLaboratory.contact.location.streetNo)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct further element from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.further, dom); + expect(toTextArr(calibrationLaboratory.contact.location.further[0].content)).toEqual(toTextContentArr(expected)); + }); +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.CoreDataType.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.CoreDataType.test.ts new file mode 100644 index 0000000..9682017 --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.CoreDataType.test.ts @@ -0,0 +1,128 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import * as fc from "fast-check"; +import { indexOf, select, toTextArr, toTextContentArr } from "../../util"; +import { CoreDataType, DCCDocument, DCCXMLElement } from "../../../src"; +import { string_ISO639_1 } from "../../Arbitraries"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:coreData"; +const xpath = { + coreData: { + countryCodeISO3166_1: `string(${base}/dcc:countryCodeISO3166_1)`, + usedLangCodeISO639_1: `${base}/dcc:usedLangCodeISO639_1`, + mandatoryLangCodeISO639_1: `${base}/dcc:mandatoryLangCodeISO639_1`, + uniqueIdentifier: `string(${base}/dcc:uniqueIdentifier)`, + identifications: { + identification: { + issuer: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + }, + receiptData: `string(${base}/dcc:receiptDate)`, + beginPerformanceDate: `string(${base}/dcc:beginPerformanceDate)`, + endPerformanceDate: `string(${base}/dcc:endPerformanceDate)`, + performanceLocation: `string(${base}/dcc:performanceLocation)`, + issueDate: `string(${base}/dcc:issueDate)`, + }, +}; + +describe("GP_Temperature_Complete_DCC: CoreDataType", () => { + let dcc: DCCDocument, coreData: CoreDataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + coreData = dcc.digitalCalibrationCertificate.administrativeData.coreData; + }); + + test("should get correct countryCodeISO3166_1 from XML", () => { + expect(coreData.countryCodeISO3166_1._text).toBe(select(xpath.coreData.countryCodeISO3166_1, dom)); + }); + + test("should get correct usedLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom); + expect(toTextArr(coreData.usedLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct mandatoryLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.mandatoryLangCodeISO639_1, dom); + expect(toTextArr(coreData.mandatoryLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct unique identifier from XML", () => { + expect(coreData.uniqueIdentifier._text).toBe(select(xpath.coreData.uniqueIdentifier, dom)); + }); + + test("should get correct identification issuer from XML", () => { + expect(coreData.identifications.identification[0].issuer._text).toBe(select(xpath.coreData.identifications.identification.issuer, dom)); + }); + + test("should get correct identification value from XML", () => { + expect(coreData.identifications.identification[0].value._text).toBe(select(xpath.coreData.identifications.identification.value, dom)); + }); + + test("should get correct identification name content from XML", () => { + const expected = <Element[]>select(xpath.coreData.identifications.identification.name.content, dom); + expect(toTextArr(coreData.identifications.identification[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct receipt date from XML", () => { + expect(coreData.receiptDate._text).toBe(select(xpath.coreData.receiptData, dom)); + }); + + test("should get correct begin performance date from XML", () => { + expect(coreData.beginPerformanceDate._text).toBe(select(xpath.coreData.beginPerformanceDate, dom)); + }); + + test("should get correct end performance date from XML", () => { + expect(coreData.endPerformanceDate._text).toBe(select(xpath.coreData.endPerformanceDate, dom)); + }); + + test("should get correct performance location from XML", () => { + expect(coreData.performanceLocation._text).toBe(select(xpath.coreData.performanceLocation, dom)); + }); + + test("should get correct issue date from XML", () => { + expect(coreData.issueDate._text).toBe(select(xpath.coreData.issueDate, dom)); + }); + + /* test for setters */ + test("should set usedLangCodeISO639_1 correctly", () => { + fc.assert( + fc.property(string_ISO639_1(), (str) => { + // add new element to array + coreData.usedLangCodeISO639_1.push(new DCCXMLElement({ _text: str })); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).toContain(str); + expect(toTextContentArr(actual)).toContain(str); + }), + ); + }); + + test("should delete usedLangCodeISO639_1 correctly", () => { + const selection = toTextContentArr(<Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom)); + fc.assert( + fc.property(fc.constantFrom(...selection), (str) => { + // get index and remove element from array + const index = indexOf(coreData.usedLangCodeISO639_1, str); + coreData.usedLangCodeISO639_1.splice(index, 1); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).not.toContain(str); + expect(toTextContentArr(actual)).not.toContain(str); + }), + ); + }); +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Customer.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Customer.test.ts new file mode 100644 index 0000000..a11d2d1 --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Customer.test.ts @@ -0,0 +1,70 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { ContactType, DCCDocument, LocationType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:customer"; +const xpath = { + customer: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:eMail)`, + location: { + city: `${base}/dcc:location/dcc:city[1]`, + countryCode: `${base}/dcc:location/dcc:countryCode[1]`, + postCode: `${base}/dcc:location/dcc:postCode[1]`, + further: `${base}/dcc:location/dcc:further[1]/dcc:content`, + }, + descriptionData: `${base}/dcc:descriptionData`, + _id: `${base}/@id`, + }, +}; + +describe("GP_Temperature_Complete_DCC: ContactType", () => { + let dcc: DCCDocument, customer: ContactType, location: LocationType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + customer = dcc.digitalCalibrationCertificate.administrativeData.customer; + location = customer.location; /* TODO: check iff this variable is used anywhere */ + }); + + test("should get correct customer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.customer.name.content, dom); + expect(toTextArr(customer.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct customer email address from XML", () => { + expect(customer.eMail._text).toBe(select(xpath.customer.email, dom)); + }); + + test("should get correct customer location city from XML", () => { + const expected = <Element[]>select(xpath.customer.location.city, dom); + expect(customer.location.city[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location county code from XML", () => { + const expected = <Element[]>select(xpath.customer.location.countryCode, dom); + expect(customer.location.countryCode[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location post code from XML", () => { + const expected = <Element[]>select(xpath.customer.location.postCode, dom); + expect(customer.location.postCode[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location further from XML", () => { + const expected = <Element[]>select(xpath.customer.location.further, dom); + + for (let i = 0; i < expected.length; i++) { + expect(customer.location.further[0].content[i]._text).toBe(expected[i].textContent); + } + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Items.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Items.test.ts new file mode 100644 index 0000000..062bf5b --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Items.test.ts @@ -0,0 +1,144 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { ItemType, DCCDocument, IdentificationType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:items"; +const xpath = { + items: { + item: { + name: { + content: `${base}/dcc:item[1]/dcc:name/dcc:content`, + }, + manufacturer: { + name: { + content: `${base}/dcc:item[1]/dcc:manufacturer/dcc:name/dcc:content`, + }, + }, + model: `string(${base}/dcc:item[1]/dcc:model)`, + identifications: { + identification1: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + identification2: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[2]/dcc:name/dcc:content`, + }, + }, + identification3: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[3]/dcc:name/dcc:content`, + }, + }, + }, + itemQuantities: { + itemQuantity: { + name: { + content: `${base}/dcc:item[1]/dcc:itemQuantities/dcc:itemQuantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:item[1]/dcc:itemQuantities/dcc:itemQuantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:item[1]/dcc:itemQuantities/dcc:itemQuantity[1]/si:real/si:unit)`, + }, + }, + }, + refType: `string(${base}/dcc:item[1]//@refType)`, + }, + }, +}; + +describe("GP_Temperature_Complete_DCC: ItemType", () => { + let dcc: DCCDocument, item: ItemType, identification1, identification2, identification3: IdentificationType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + item = dcc.digitalCalibrationCertificate.administrativeData.items.item[0]; + identification1 = item.identifications.identification[0]; + identification2 = item.identifications.identification[1]; + identification3 = item.identifications.identification[2]; + }); + + test("should get correct item name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.name.content, dom); + expect(toTextArr(item.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item manufacturer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.manufacturer.name.content, dom); + expect(toTextArr(item.manufacturer.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item model from XML", () => { + expect(item.model._text).toBe(select(xpath.items.item.model, dom)); + }); + + test("should get correct identification 1 issuer from XML", () => { + expect(identification1.issuer._text).toBe(select(xpath.items.item.identifications.identification1.issuer, dom)); + }); + + test("should get correct identification 1 value from XML", () => { + expect(identification1.value._text).toBe(select(xpath.items.item.identifications.identification1.value, dom)); + }); + + test("should get correct identification 1 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification1.name.content, dom); + expect(toTextArr(identification1.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct identification 2 issuer from XML", () => { + expect(identification2.issuer._text).toBe(select(xpath.items.item.identifications.identification2.issuer, dom)); + }); + + test("should get correct identification 2 value from XML", () => { + expect(identification2.value._text).toBe(select(xpath.items.item.identifications.identification2.value, dom)); + }); + + test("should get correct identification 2 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification2.name.content, dom); + expect(toTextArr(identification2.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct identification 3 issuer from XML", () => { + expect(identification3.issuer._text).toBe(select(xpath.items.item.identifications.identification3.issuer, dom)); + }); + + test("should get correct identification 3 value from XML", () => { + expect(identification3.value._text).toBe(select(xpath.items.item.identifications.identification3.value, dom)); + }); + + test("should get correct identification 3 name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.identifications.identification3.name.content, dom); + expect(toTextArr(identification3.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item quantity name content from XML", () => { + const expected = <Element[]>select(xpath.items.item.itemQuantities.itemQuantity.name.content, dom); + expect(toTextArr(item.itemQuantities.itemQuantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item quantity real value from XML", () => { + expect(item.itemQuantities.itemQuantity[0].real.value._text).toBe(select(xpath.items.item.itemQuantities.itemQuantity.si_real.si_value, dom)); + }); + + test("should get correct item quantity real unit from XML", () => { + expect(item.itemQuantities.itemQuantity[0].real.unit._text).toBe(select(xpath.items.item.itemQuantities.itemQuantity.si_real.si_unit, dom)); + }); + + test("should get correct item refType from XML", () => { + expect(item._attr.refType).toBe(select(xpath.items.item.refType, dom)); + }); + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.RefTypeDefinitons.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.RefTypeDefinitons.test.ts new file mode 100644 index 0000000..0400f0b --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.RefTypeDefinitons.test.ts @@ -0,0 +1,72 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, RefTypeDefinitionType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:refTypeDefinitions/dcc:refTypeDefinition[1]"; +const xpath = { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + description: { + name: { + content: `${base}/dcc:description/dcc:name/dcc:content`, + }, + content: `${base}/dcc:description/dcc:content`, + }, + namespace: `string(${base}/dcc:namespace)`, + link: `string(${base}/dcc:link)`, + release: `string(${base}/dcc:release)`, + value: `string(${base}/dcc:value)`, + procedure: `string(${base}/dcc:procedure)`, +}; + +describe("GP_Temperature_Complete_DCC: RefTypeDefinitionType", () => { + let dcc: DCCDocument, refTypeDefinition: RefTypeDefinitionType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + refTypeDefinition = dcc.digitalCalibrationCertificate.administrativeData.refTypeDefinitions.refTypeDefinition[0]; + }); + + test("should get correct name from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.name.content, dom); + expect(toTextArr(refTypeDefinition.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct description name from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.description.name.content, dom); + expect(toTextArr(refTypeDefinition.description.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.description.content, dom); + expect(toTextArr(refTypeDefinition.description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct namespace from XML", () => { + expect(refTypeDefinition.namespace._text).toBe(select(xpath.namespace, dom)); + }); + + test("should get correct link from XML", () => { + expect(refTypeDefinition.link._text).toBe(select(xpath.link, dom)); + }); + + test("should get correct release from XML", () => { + expect(refTypeDefinition.release._text).toBe(select(xpath.release, dom)); + }); + + test("should get correct value from XML", () => { + expect(refTypeDefinition.value._text).toBe(select(xpath.value, dom)); + }); + + test("should get correct procedure from XML", () => { + expect(refTypeDefinition.procedure._text).toBe(select(xpath.procedure, dom)); + }); +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.RespPersons.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.RespPersons.test.ts new file mode 100644 index 0000000..768e9e2 --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.RespPersons.test.ts @@ -0,0 +1,56 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { RespPersonType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:respPersons"; +const xpath = { + respPersons: { + respPerson1: { + person: { + name: { + content: `${base}/dcc:respPerson[1]/dcc:person/dcc:name/dcc:content`, + }, + }, + mainSigner: `string(${base}/dcc:respPerson[1]/dcc:mainSigner)`, + }, + respPerson2: { + person: { + name: { + content: `${base}/dcc:respPerson[2]/dcc:person/dcc:name/dcc:content`, + }, + }, + }, + }, +}; + +describe("GP_Temperature_Complete_DCC: RespPersonType", () => { + let dcc: DCCDocument, respPerson1, respPerson2: RespPersonType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + respPerson1 = dcc.digitalCalibrationCertificate.administrativeData.respPersons.respPerson[0]; + respPerson2 = dcc.digitalCalibrationCertificate.administrativeData.respPersons.respPerson[1]; + }); + + test("should get correct responsible person 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.respPersons.respPerson1.person.name.content, dom); + expect(toTextArr(respPerson1.person.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct responsible person 1 main signer flag from XML", () => { + expect(respPerson1.mainSigner._text).toBe(select(xpath.respPersons.respPerson1.mainSigner, dom)); + }); + + test("should get correct responsible person 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.respPersons.respPerson2.person.name.content, dom); + expect(toTextArr(respPerson2.person.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.SoftwareListType.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.SoftwareListType.test.ts new file mode 100644 index 0000000..39aadae --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.SoftwareListType.test.ts @@ -0,0 +1,60 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { SoftwareListType, DCCDocument, SoftwareType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:dccSoftware/dcc:software"; +const xpath = { + software: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + release: `string(${base}/dcc:release)`, + type: `string(${base}/dcc:type)`, + description: { + name: { + content: `${base}/dcc:description/dcc:name/dcc:content`, + }, + content: `${base}/dcc:description/dcc:content`, + }, + }, +}; + +describe("GP_Temperature_Complete_DCC: DccSoftwareType", () => { + let dcc: DCCDocument, dccSoftware: SoftwareListType, software: SoftwareType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + dccSoftware = dcc.digitalCalibrationCertificate.administrativeData.dccSoftware; + software = dccSoftware.software[0]; + }); + + test("should get correct software name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.software.name.content, dom); + expect(toTextArr(software.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct software release version of software from XML", () => { + expect(software.release._text).toBe(select(xpath.software.release, dom)); + }); + + test("should get correct software type of software from XML", () => { + expect(software.type._text).toBe(select(xpath.software.type, dom)); + }); + + test("should get correct description name content of software from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.software.description.name.content, dom); + expect(toTextArr(software.description.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct description content of software from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.software.description.content, dom); + expect(toTextArr(software.description.content)).toEqual(toTextContentArr(expected)); + }); +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Statements.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Statements.test.ts new file mode 100644 index 0000000..10288f8 --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/AdministrativeData.Statements.test.ts @@ -0,0 +1,127 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { StatementMetaDataType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:statements"; +const xpath = { + statements: { + statement1: { + declaration: { + content: `${base}/dcc:statement[1]/dcc:declaration/dcc:content`, + }, + respAuthority: { + name: { + content: `${base}/dcc:statement[1]/dcc:respAuthority/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:statement[1]/dcc:respAuthority/dcc:eMail)`, + location: { + city: `string(${base}/dcc:statement[1]/dcc:respAuthority/dcc:location/dcc:city)`, + countryCode: `string(${base}/dcc:statement[1]/dcc:respAuthority/dcc:location/dcc:countryCode)`, + postCode: `string(${base}/dcc:statement[1]/dcc:respAuthority/dcc:location/dcc:postCode)`, + }, + }, + conformity: `string(${base}/dcc:statement[1]/dcc:conformity)`, + refType: `string(${base}/dcc:statement[1]/@refType)`, + }, + statement2: { + declaration: { + content: `${base}/dcc:statement[2]/dcc:declaration/dcc:content`, + }, + date: `string(${base}/dcc:statement[2]/dcc:date)`, + respAuthority: { + name: { + content: `${base}/dcc:statement[2]/dcc:respAuthority/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:statement[2]/dcc:respAuthority/dcc:eMail)`, + location: { + city: `string(${base}/dcc:statement[2]/dcc:respAuthority/dcc:location/dcc:city)`, + countryCode: `string(${base}/dcc:statement[2]/dcc:respAuthority/dcc:location/dcc:countryCode)`, + postCode: `string(${base}/dcc:statement[2]/dcc:respAuthority/dcc:location/dcc:postCode)`, + }, + }, + refType: `string(${base}/dcc:statement[2]/@refType)`, + }, + }, +}; + +describe("GP_Temperature_Complete_DCC: StatementMetaDataType", () => { + let dcc: DCCDocument, statement1, statement2: StatementMetaDataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + statement1 = dcc.digitalCalibrationCertificate.administrativeData.statements.statement[0]; + statement2 = dcc.digitalCalibrationCertificate.administrativeData.statements.statement[1]; + }); + + test("should get correct statement 1 declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement1.declaration.content, dom); + expect(toTextArr(statement1.declaration.content)).toEqual(toTextContentArr(expected)); + }); + + /* responsible authority 1 */ + test("should get correct statement 1 responsible authority name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement1.respAuthority.name.content, dom); + expect(toTextArr(statement1.respAuthority.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 1 responsible authority email from XML", () => { + expect(statement1.respAuthority.eMail._text).toBe(select(xpath.statements.statement1.respAuthority.email, dom)); + }); + + test("should get correct statement 1 responsible authority location city from XML", () => { + expect(statement1.respAuthority.location.city[0]._text).toBe(select(xpath.statements.statement1.respAuthority.location.city, dom)); + }); + test("should get correct statement 1 responsible authority location country code from XML", () => { + expect(statement1.respAuthority.location.countryCode[0]._text).toBe(select(xpath.statements.statement1.respAuthority.location.countryCode, dom)); + }); + test("should get correct statement 1 responsible authority location post code from XML", () => { + expect(statement1.respAuthority.location.postCode[0]._text).toBe(select(xpath.statements.statement1.respAuthority.location.postCode, dom)); + }); + + test("should get correct statement 1 conformity from XML", () => { + expect(statement1.conformity._text).toBe(select(xpath.statements.statement1.conformity, dom)); + }); + + test("should get correct statement 2 declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement2.declaration.content, dom); + expect(toTextArr(statement2.declaration.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 2 refType from XML", () => { + expect(statement2.date._text).toBe(select(xpath.statements.statement2.date, dom)); + }); + + /* responsible authority 2 */ + test("should get correct statement 2 responsible authority name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.statements.statement2.respAuthority.name.content, dom); + expect(toTextArr(statement2.respAuthority.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement 2 responsible authority email from XML", () => { + expect(statement2.respAuthority.eMail._text).toBe(select(xpath.statements.statement2.respAuthority.email, dom)); + }); + + test("should get correct statement 2 responsible authority location city from XML", () => { + expect(statement2.respAuthority.location.city[0]._text).toBe(select(xpath.statements.statement2.respAuthority.location.city, dom)); + }); + test("should get correct statement 2 responsible authority location country code from XML", () => { + expect(statement2.respAuthority.location.countryCode[0]._text).toBe(select(xpath.statements.statement2.respAuthority.location.countryCode, dom)); + }); + test("should get correct statement 2 responsible authority location post code from XML", () => { + expect(statement2.respAuthority.location.postCode[0]._text).toBe(select(xpath.statements.statement2.respAuthority.location.postCode, dom)); + }); + + test("should get correct statement 2 refType from XML", () => { + expect(statement2._attr.refType).toBe(select(xpath.statements.statement2.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/DigitalCalibrationCertificateType.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/DigitalCalibrationCertificateType.test.ts new file mode 100644 index 0000000..ae1ad14 --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/DigitalCalibrationCertificateType.test.ts @@ -0,0 +1,21 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select } from "../../util"; + +const VERSION_XPATH = "string(/dcc:digitalCalibrationCertificate/@schemaVersion)"; + +describe("GP_Temperature_Complete_DCC: DigitalCalibrationCertificateType", () => { + let xml, dcc, dom; + + beforeEach(() => { + ({ xml, dcc, dom } = xmlEnv.recreateEnv()); + }); + + test("should get correct schemaVersion from XML", () => { + const expectedVersion = select(VERSION_XPATH, dom); + expect(dcc.digitalCalibrationCertificate._attr.schemaVersion).toBe(expectedVersion); + }); +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts new file mode 100644 index 0000000..6d8fbac --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts @@ -0,0 +1,218 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, InfluenceConditionListType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:influenceConditions"; +const xpath = { + measurementResults: { + measurementResult: { + influenceConditions: { + influenceCondition1: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:influenceCondition[1]/dcc:description/dcc:content`, + }, + data: { + quantity1: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[2]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[2]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:influenceCondition[1]//@refType)`, + }, + influenceCondition2: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content`, + contentDE: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content[@lang='de']`, + contentEN: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content[@lang='en']`, + }, + data: { + quantity1: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:influenceCondition[2]//@refType)`, + }, + }, + }, + }, +}; + +describe("GP_Temperature_Complete_DCC: InfluenceConditionListType", () => { + let dcc: DCCDocument, influenceConditions: InfluenceConditionListType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + influenceConditions = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].influenceConditions; + }); + + test("should get correct influence condition 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.description.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 quantity name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 quantity si:value from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity1.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 1 quantity si:unit from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity1.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 1 quantity 1 refType from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity1.refType, dom), + ); + }); + + test("should get correct influence condition 1 quantity 2 si:value from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[1].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity2.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 1 quantity 2 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[1].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity2.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 1 quantity 2 refType from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity2.refType, dom), + ); + }); + + test("should get correct influence condition 1 refType from XML", () => { + expect(influenceConditions.influenceCondition[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.refType, dom), + ); + }); + + test("should get correct influence condition 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.description.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 1 si:value from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 2 quantity 1 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 2 quantity 1 refType from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.refType, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].data.quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 2 si:value from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 refType from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.refType, dom), + ); + }); + + test("should get correct influence condition 2 refType from XML", () => { + expect(influenceConditions.influenceCondition[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.refType, dom), + ); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts new file mode 100644 index 0000000..86b8a4d --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts @@ -0,0 +1,58 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, MeasuringEquipmentType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:measuringEquipments/dcc:measuringEquipment[1]"; +const xpath = { + measuringEquipments: { + measuringEquipment: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + identifications: { + identification: { + issuer: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:value)`, + }, + }, + refType: `string(${base}//@refType)`, + }, + }, +}; + +describe("GP_Temperature_Complete_DCC: MeasuringEquipmentType", () => { + let dcc: DCCDocument, measuringEquipment: MeasuringEquipmentType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + measuringEquipment = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].measuringEquipments.measuringEquipment[0]; + }); + + test("should get correct measurement result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measuringEquipments.measuringEquipment.name.content, dom); + expect(toTextArr(measuringEquipment.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct measuring equipment 1 identification issuer from XML", () => { + expect(measuringEquipment.identifications.identification[0].issuer._text).toBe( + select(xpath.measuringEquipments.measuringEquipment.identifications.identification.issuer, dom), + ); + }); + + test("should get correct measuring equipment 1 identification value from XML", () => { + expect(measuringEquipment.identifications.identification[0].value._text).toBe( + select(xpath.measuringEquipments.measuringEquipment.identifications.identification.value, dom), + ); + }); + + test("should get correct measuring equipment 1 refType from XML", () => { + expect(measuringEquipment._attr.refType).toBe(select(xpath.measuringEquipments.measuringEquipment.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.Name.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.Name.test.ts new file mode 100644 index 0000000..f5f95f7 --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.Name.test.ts @@ -0,0 +1,35 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, MeasurementResultType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults"; +const xpath = { + measurementResults: { + measurementResult: { + name: { + content: `${base}/dcc:measurementResult[1]/dcc:name/dcc:content`, + }, + }, + }, +}; + +describe("GP_Temperature_Complete_DCC: MeasurementResultType", () => { + let dcc: DCCDocument, measurementResult: MeasurementResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + measurementResult = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0]; + }); + + test("should get correct measurement result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.name.content, dom); + expect(toTextArr(measurementResult.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.Results.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.Results.test.ts new file mode 100644 index 0000000..7b01f47 --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.Results.test.ts @@ -0,0 +1,737 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, ResultType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:results"; +const xpath = { + measurementResults: { + measurementResult: { + results: { + result: { + name: { + content: `${base}/dcc:result[1]/dcc:name/dcc:content`, + }, + data: { + list: { + quantity1: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]//@refType)`, + }, + quantity3: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:name/dcc:content`, + }, + si_realListXMLList: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:unitXMLList)`, + si_expandedUncXMLList: { + si_uncertaintyXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:uncertaintyXMLList)`, + si_coverageFactorXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:coverageFactorXMLList)`, + si_coverageProbabilityXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:coverageProbabilityXMLList)`, + si_distributionXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:distributionXMLList)`, + }, + }, + measurementMetaData: { + metaData: { + declaration: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData[1]/dcc:declaration/dcc:name/dcc:content`, + }, + }, + conformityXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:conformityXMLList)`, + data: { + quantity1: { + si_realListXMLList: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:realListXMLList/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:realListXMLList/si:unitXMLList)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + si_realListXMLList: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[2]/si:realListXMLList/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[2]/si:realListXMLList/si:unitXMLList)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:measurementMetaData/dcc:metaData//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/@refType)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list//@refType)`, + }, + quantity1: { + noQuantity: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:quantity[1]/dcc:noQuantity/dcc:name/dcc:content`, + }, + content: `${base}/dcc:result[1]/dcc:data/dcc:quantity[1]/dcc:noQuantity/dcc:content`, + file: { + fileName: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[1]/dcc:noQuantity/dcc:file[1]/dcc:fileName)`, + mimeType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[1]/dcc:noQuantity/dcc:file[1]/dcc:mimeType)`, + dataBase64: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[1]/dcc:noQuantity/dcc:file[1]/dcc:dataBase64)`, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[1]/dcc:noQuantity/dcc:file[1]//@refType)`, + }, + formula: { + latex: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[1]/dcc:noQuantity/dcc:formula[1]/dcc:latex)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + charsXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[2]/dcc:charsXMLList)`, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[2]//@refType)`, + }, + quantity3: { + si_constant: { + si_label: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[3]/si:constant/si:label)`, + si_value: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[3]/si:constant/si:value)`, + si_unit: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[3]/si:constant/si:unit)`, + si_dateTime: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[3]/si:constant/si:dateTime)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[3]//@refType)`, + }, + quantity4: { + si_real: { + si_label: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[4]/si:real/si:label)`, + si_value: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[4]/si:real/si:value)`, + si_unit: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[4]/si:real/si:unit)`, + si_dateTime: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[4]/si:real/si:dateTime)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[4]//@refType)`, + }, + quantity5: { + si_realListXMLList: { + si_labelXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[5]/si:realListXMLList/si:labelXMLList)`, + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[5]/si:realListXMLList/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[5]/si:realListXMLList/si:unitXMLList)`, + si_dateTimeXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[5]/si:realListXMLList/si:dateTimeXMLList)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[5]//@refType)`, + }, + quantity6: { + si_hybrid: { + si_constant1: { + si_label: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[6]/si:hybrid/si:constant[1]/si:label)`, + si_value: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[6]/si:hybrid/si:constant[1]/si:value)`, + si_unit: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[6]/si:hybrid/si:constant[1]/si:unit)`, + si_dateTime: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[6]/si:hybrid/si:constant[1]/si:dateTime)`, + }, + si_constant2: { + si_label: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[6]/si:hybrid/si:constant[2]/si:label)`, + si_value: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[6]/si:hybrid/si:constant[2]/si:value)`, + si_unit: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[6]/si:hybrid/si:constant[2]/si:unit)`, + si_dateTime: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[6]/si:hybrid/si:constant[2]/si:dateTime)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[6]//@refType)`, + }, + quantity7: { + si_hybrid: { + si_real1: { + si_label: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[7]/si:hybrid/si:real[1]/si:label)`, + si_value: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[7]/si:hybrid/si:real[1]/si:value)`, + si_unit: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[7]/si:hybrid/si:real[1]/si:unit)`, + si_dateTime: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[7]/si:hybrid/si:real[1]/si:dateTime)`, + }, + si_real2: { + si_label: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[7]/si:hybrid/si:real[2]/si:label)`, + si_value: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[7]/si:hybrid/si:real[2]/si:value)`, + si_unit: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[7]/si:hybrid/si:real[2]/si:unit)`, + si_dateTime: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[7]/si:hybrid/si:real[2]/si:dateTime)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[7]//@refType)`, + }, + quantity8: { + si_hybrid: { + si_realListXMLList1: { + si_labelXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[8]/si:hybrid/si:realListXMLList[1]/si:labelXMLList)`, + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[8]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[8]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + si_dateTimeXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[8]/si:hybrid/si:realListXMLList[1]/si:dateTimeXMLList)`, + }, + si_realListXMLList2: { + si_labelXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[8]/si:hybrid/si:realListXMLList[2]/si:labelXMLList)`, + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[8]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[8]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + si_dateTimeXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[8]/si:hybrid/si:realListXMLList[2]/si:dateTimeXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:quantity[8]//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]//@refType)`, + }, + }, + }, + }, +}; + +describe("GP_Temperature_Complete_DCC: ResultType", () => { + let dcc: DCCDocument, result: ResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + result = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].results.result[0]; + }); + + test("should get correct result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.name.content, dom); + expect(toTextArr(result.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result list quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result list quantity 1 hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result list quantity 1 hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result list quantity 1 hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result list quantity 1 hybrid si:unitXMLList 2: from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result list quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result list quantity 2 hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result list quantity 2 hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result list quantity 2 hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result list quantity 2 hybrid si:unitXMLList 2: from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result list quantity 3 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[2].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result list quantity 3 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_valueXMLList, dom), + ); + }); + + test("should get correct result list quantity 3 si:unitXMLList from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_unitXMLList, dom), + ); + }); + + test("should get correct result list quantity 3 uncertainty list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.uncertaintyXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_uncertaintyXMLList, dom), + ); + }); + + test("should get correct result list quantity 3 uncertainty coverage factor list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.coverageFactorXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_coverageFactorXMLList, + dom, + ), + ); + }); + + test("should get correct result list quantity 3 uncertainty coverage probability list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.coverageProbabilityXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_coverageProbabilityXMLList, + dom, + ), + ); + }); + + test("should get correct result list quantity 3 uncertainty distribution list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.distributionXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_distributionXMLList, + dom, + ), + ); + }); + + test("should get correct result list quantity 3 meta data declaration name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.declaration.name.content, dom) + ); + expect(toTextArr(result.data.list[0].quantity[2].measurementMetaData.metaData[0].declaration.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result list quantity 3 meta data conformityXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].conformityXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.conformityXMLList, dom), + ); + }); + + test("should get correct result list quantity 3 meta data quantity 1 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[0].realListXMLList.valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity1.si_realListXMLList + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result list quantity 3 meta data quantity 1 si:unitXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[0].realListXMLList.unitXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity1.si_realListXMLList + .si_unitXMLList, + dom, + ), + ); + }); + + test("should get correct result list quantity 3 meta data quantity 2 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[1].realListXMLList.valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity2.si_realListXMLList + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result list quantity 3 meta data quantity 2 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[1].realListXMLList.valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity2.si_realListXMLList + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result list quantity 3 meta data quantity 2 si:unitXMLList from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0].data.quantity[1].realListXMLList.unitXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.data.quantity2.si_realListXMLList + .si_unitXMLList, + dom, + ), + ); + }); + + test("should get correct result refType from XML", () => { + expect(result._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.refType, dom)); + }); + + test("should get correct result data list refType from XML", () => { + expect(result.data.list[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.list.refType, dom)); + }); + + test("should get correct result list quantity 1 refType from XML", () => { + expect(result.data.list[0].quantity[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.refType, dom), + ); + }); + + test("should get correct result list quantity2 refType from XML", () => { + expect(result.data.list[0].quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.refType, dom), + ); + }); + + test("should get correct result list quantity3 refType from XML", () => { + expect(result.data.list[0].quantity[2]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.refType, dom), + ); + }); + + test("should get correct result list quantity 3 meta data refType from XML", () => { + expect(result.data.list[0].quantity[2].measurementMetaData.metaData[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.measurementMetaData.metaData.refType, dom), + ); + }); + + test("should get correct result list quantity 2 refType from XML", () => { + expect(result.data.list[0].quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.refType, dom), + ); + }); + + test("should get correct result list quantity 3 refType from XML", () => { + expect(result.data.list[0].quantity[2]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.refType, dom), + ); + }); + + test("should get correct result no quantity name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.quantity1.noQuantity.name.content, dom); + expect(toTextArr(result.data.quantity[0].noQuantity.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result no quantity content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.quantity1.noQuantity.content, dom); + expect(toTextArr(result.data.quantity[0].noQuantity.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result no quantity file fileName from XML", () => { + expect(result.data.quantity[0].noQuantity.file[0].fileName._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity1.noQuantity.file.fileName, dom), + ); + }); + + test("should get correct result no quantity file mimeType from XML", () => { + expect(result.data.quantity[0].noQuantity.file[0].mimeType._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity1.noQuantity.file.mimeType, dom), + ); + }); + + test("should get correct result no quantity file dataBase64 from XML", () => { + expect(result.data.quantity[0].noQuantity.file[0].dataBase64._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity1.noQuantity.file.dataBase64, dom), + ); + }); + + test("should get correct result no quantity file refType from XML", () => { + expect(result.data.quantity[0].noQuantity.file[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity1.noQuantity.file.refType, dom), + ); + }); + + test("should get correct result no quantity formula latex from XML", () => { + expect(result.data.quantity[0].noQuantity.formula[0].latex._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity1.noQuantity.formula.latex, dom), + ); + }); + + test("should get correct result no quantity file refType from XML", () => { + expect(result.data.quantity[0].noQuantity.file[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity1.noQuantity.file.refType, dom), + ); + }); + + test("should get correct result charsXMLList value from XML", () => { + expect(result.data.quantity[1].charsXMLList._text).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity2.charsXMLList, dom)); + }); + + test("should get correct result const label from XML", () => { + expect(result.data.quantity[2].constant.label._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity3.si_constant.si_label, dom), + ); + }); + + test("should get correct result const value from XML", () => { + expect(result.data.quantity[2].constant.value._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity3.si_constant.si_value, dom), + ); + }); + + test("should get correct result const unit from XML", () => { + expect(result.data.quantity[2].constant.unit._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity3.si_constant.si_unit, dom), + ); + }); + + test("should get correct result const dateTime from XML", () => { + expect(result.data.quantity[2].constant.dateTime._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity3.si_constant.si_dateTime, dom), + ); + }); + + test("should get correct result real label from XML", () => { + expect(result.data.quantity[3].real.label._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity4.si_real.si_label, dom), + ); + }); + + test("should get correct result real value from XML", () => { + expect(result.data.quantity[3].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity4.si_real.si_value, dom), + ); + }); + + test("should get correct result real unit from XML", () => { + expect(result.data.quantity[3].real.unit._text).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity4.si_real.si_unit, dom)); + }); + + test("should get correct result real dateTime from XML", () => { + expect(result.data.quantity[3].real.dateTime._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity4.si_real.si_dateTime, dom), + ); + }); + + test("should get correct result realListXMLList label list from XML", () => { + expect(result.data.quantity[4].realListXMLList.labelXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity5.si_realListXMLList.si_labelXMLList, dom), + ); + }); + + test("should get correct result realListXMLList value list from XML", () => { + expect(result.data.quantity[4].realListXMLList.valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity5.si_realListXMLList.si_valueXMLList, dom), + ); + }); + + test("should get correct result realListXMLList unit list from XML", () => { + expect(result.data.quantity[4].realListXMLList.unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity5.si_realListXMLList.si_unitXMLList, dom), + ); + }); + + test("should get correct result realListXMLList dateTime list from XML", () => { + expect(result.data.quantity[4].realListXMLList.dateTimeXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity5.si_realListXMLList.si_dateTimeXMLList, dom), + ); + }); + + test("should get correct result hybrid const 1 label from XML", () => { + expect(result.data.quantity[5].hybrid.constant[0].label._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity6.si_hybrid.si_constant1.si_label, dom), + ); + }); + + test("should get correct result hybrid const 1 value from XML", () => { + expect(result.data.quantity[5].hybrid.constant[0].value._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity6.si_hybrid.si_constant1.si_value, dom), + ); + }); + + test("should get correct result hybrid const 1 unit from XML", () => { + expect(result.data.quantity[5].hybrid.constant[0].unit._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity6.si_hybrid.si_constant1.si_unit, dom), + ); + }); + + test("should get correct result hybrid const 1 dateTime from XML", () => { + expect(result.data.quantity[5].hybrid.constant[0].dateTime._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity6.si_hybrid.si_constant1.si_dateTime, dom), + ); + }); + + test("should get correct result hybrid const 2 label from XML", () => { + expect(result.data.quantity[5].hybrid.constant[1].label._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity6.si_hybrid.si_constant2.si_label, dom), + ); + }); + + test("should get correct result hybrid const 2 value from XML", () => { + expect(result.data.quantity[5].hybrid.constant[1].value._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity6.si_hybrid.si_constant2.si_value, dom), + ); + }); + + test("should get correct result hybrid const 2 unit from XML", () => { + expect(result.data.quantity[5].hybrid.constant[1].unit._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity6.si_hybrid.si_constant2.si_unit, dom), + ); + }); + + test("should get correct result hybrid const 2 dateTime from XML", () => { + expect(result.data.quantity[5].hybrid.constant[1].dateTime._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity6.si_hybrid.si_constant2.si_dateTime, dom), + ); + }); + + test("should get correct result hybrid real 1 label from XML", () => { + expect(result.data.quantity[6].hybrid.real[0].label._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity7.si_hybrid.si_real1.si_label, dom), + ); + }); + + test("should get correct result hybrid real 1 value from XML", () => { + expect(result.data.quantity[6].hybrid.real[0].value._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity7.si_hybrid.si_real1.si_value, dom), + ); + }); + + test("should get correct result hybrid real 1 unit from XML", () => { + expect(result.data.quantity[6].hybrid.real[0].unit._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity7.si_hybrid.si_real1.si_unit, dom), + ); + }); + + test("should get correct result hybrid real 1 dateTime from XML", () => { + expect(result.data.quantity[6].hybrid.real[0].dateTime._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity7.si_hybrid.si_real1.si_dateTime, dom), + ); + }); + + test("should get correct result hybrid real 2 label from XML", () => { + expect(result.data.quantity[6].hybrid.real[1].label._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity7.si_hybrid.si_real2.si_label, dom), + ); + }); + + test("should get correct result hybrid real 2 value from XML", () => { + expect(result.data.quantity[6].hybrid.real[1].value._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity7.si_hybrid.si_real2.si_value, dom), + ); + }); + + test("should get correct result hybrid real 2 unit from XML", () => { + expect(result.data.quantity[6].hybrid.real[1].unit._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity7.si_hybrid.si_real2.si_unit, dom), + ); + }); + + test("should get correct result hybrid real 2 dateTime from XML", () => { + expect(result.data.quantity[6].hybrid.real[1].dateTime._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity7.si_hybrid.si_real2.si_dateTime, dom), + ); + }); + + test("should get correct result hybrid realListXMLList 1 label from XML", () => { + expect(result.data.quantity[7].hybrid.realListXMLList[0].labelXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity8.si_hybrid.si_realListXMLList1.si_labelXMLList, dom), + ); + }); + + test("should get correct result hybrid realListXMLList 1 value from XML", () => { + expect(result.data.quantity[7].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity8.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result hybrid realListXMLList 1 unit from XML", () => { + expect(result.data.quantity[7].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity8.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result hybrid realListXMLList 1 dateTime from XML", () => { + expect(result.data.quantity[7].hybrid.realListXMLList[0].dateTimeXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity8.si_hybrid.si_realListXMLList1.si_dateTimeXMLList, dom), + ); + }); + + test("should get correct result hybrid realListXMLList 2 label from XML", () => { + expect(result.data.quantity[7].hybrid.realListXMLList[1].labelXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity8.si_hybrid.si_realListXMLList2.si_labelXMLList, dom), + ); + }); + + test("should get correct result hybrid realListXMLList 2 value from XML", () => { + expect(result.data.quantity[7].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity8.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result hybrid realListXMLList 2 unit from XML", () => { + expect(result.data.quantity[7].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity8.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result hybrid realListXMLList 2 dateTime from XML", () => { + expect(result.data.quantity[7].hybrid.realListXMLList[1].dateTimeXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.quantity8.si_hybrid.si_realListXMLList2.si_dateTimeXMLList, dom), + ); + }); + + test("should get correct result no quantity refType from XML", () => { + expect(result.data.quantity[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity1.refType, dom)); + }); + + test("should get correct result charsXMLList refType from XML", () => { + expect(result.data.quantity[1]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity2.refType, dom)); + }); + + test("should get correct result const refType from XML", () => { + expect(result.data.quantity[2]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity3.refType, dom)); + }); + + test("should get correct result real refType from XML", () => { + expect(result.data.quantity[3]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity4.refType, dom)); + }); + + test("should get correct result realListXMLList refType from XML", () => { + expect(result.data.quantity[4]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity5.refType, dom)); + }); + + test("should get correct result hybrid const refType from XML", () => { + expect(result.data.quantity[5]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity6.refType, dom)); + }); + + test("should get correct result hybrid real refType from XML", () => { + expect(result.data.quantity[6]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity7.refType, dom)); + }); + + test("should get correct result hybrid realListXMLList refType from XML", () => { + expect(result.data.quantity[7]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.quantity8.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.UsedMethods.test.ts b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.UsedMethods.test.ts new file mode 100644 index 0000000..d16b268 --- /dev/null +++ b/tests/DCC/GP_Temperatur_v3.2.0_DCC/MeasurementResults.MeasurementResult.UsedMethods.test.ts @@ -0,0 +1,44 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, UsedMethodListType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]"; +const xpath = { + measurementResults: { + measurementResult: { + usedMethods: { + usedMethod1: { + name: { + content: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:name/dcc:content`, + }, + refType: `string(${base}/dcc:usedMethods/dcc:usedMethod[1]//@refType)`, + }, + }, + }, + }, +}; + +describe("GP_Temperature_Complete_DCC: UsedMethodListType", () => { + let dcc: DCCDocument, usedMethods: UsedMethodListType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + usedMethods = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].usedMethods; + }); + + test("should get correct used method 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.name.content, dom); + expect(toTextArr(usedMethods.usedMethod[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct used method 1 refType from XML", () => { + expect(usedMethods.usedMethod[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts b/tests/DCC/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts new file mode 100644 index 0000000..5f4974e --- /dev/null +++ b/tests/DCC/MeasurementResults.MeasurementResult.InfluenceConditions.test.ts @@ -0,0 +1,249 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +import { select, toTextArr, toTextContentArr } from "../util"; +import { DCCDocument, InfluenceConditionListType } from "../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:influenceConditions"; +const xpath = { + measurementResults: { + measurementResult: { + influenceConditions: { + influenceCondition1: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:name/dcc:content`, + }, + data: { + quantity: { + name: { + content: `${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[1]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + }, + }, + refType: `string(${base}/dcc:influenceCondition[1]//@refType)`, + }, + influenceCondition2: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content`, + contentDE: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content[@lang='de']`, + contentEN: `${base}/dcc:influenceCondition[2]/dcc:description/dcc:content[@lang='en']`, + }, + data: { + quantity1: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[2]/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:influenceCondition[2]//@refType)`, + }, + influenceCondition3: { + name: { + content: `${base}/dcc:influenceCondition[3]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:influenceCondition[3]/dcc:description/dcc:content`, + contentDE: `${base}/dcc:influenceCondition[3]/dcc:description/dcc:content[@lang='de']`, + contentEN: `${base}/dcc:influenceCondition[3]/dcc:description/dcc:content[@lang='en']`, + }, + data: { + quantity1: { + name: { + content: `${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[1]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[1]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_real: { + si_value: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[2]/si:real/si:value)`, + si_unit: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[2]/si:real/si:unit)`, + }, + refType: `string(${base}/dcc:influenceCondition[3]/dcc:data/dcc:quantity[2]//@refType)`, + }, + }, + refType: `string(${base}/dcc:influenceCondition[3]//@refType)`, + }, + }, + }, + }, +}; + +describe("InfluenceConditionListType", () => { + let dcc: DCCDocument, influenceConditions: InfluenceConditionListType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + influenceConditions = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].influenceConditions; + }); + + test("should get correct influence condition 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 quantity name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[0].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 1 quantity si:value from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 1 quantity si:unit from XML", () => { + expect(influenceConditions.influenceCondition[0].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.data.quantity.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 1 refType from XML", () => { + expect(influenceConditions.influenceCondition[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition1.refType, dom), + ); + }); + + test("should get correct influence condition 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.description.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 1 si:value from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 2 quantity 1 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity1.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[1].data.quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 2 quantity 2 si:value from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 2 quantity 2 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[1].data.quantity[1].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.data.quantity2.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 2 refType from XML", () => { + expect(influenceConditions.influenceCondition[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition2.refType, dom), + ); + }); + + test("should get correct influence condition 3 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[2].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 3 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.description.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[2].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 3 quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity1.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[2].data.quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 3 quantity 1 si:value from XML", () => { + expect(influenceConditions.influenceCondition[2].data.quantity[0].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity1.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 3 quantity 1 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[2].data.quantity[0].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity1.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 3 quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity2.name.content, dom); + expect(toTextArr(influenceConditions.influenceCondition[2].data.quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct influence condition 3 quantity 2 si:value from XML", () => { + expect(influenceConditions.influenceCondition[2].data.quantity[1].real.value._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity2.si_real.si_value, dom), + ); + }); + + test("should get correct influence condition 3 quantity 2 si:unit from XML", () => { + expect(influenceConditions.influenceCondition[2].data.quantity[1].real.unit._text).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.data.quantity2.si_real.si_unit, dom), + ); + }); + + test("should get correct influence condition 3 refType from XML", () => { + expect(influenceConditions.influenceCondition[2]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.influenceConditions.influenceCondition3.refType, dom), + ); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts b/tests/DCC/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts new file mode 100644 index 0000000..8107d84 --- /dev/null +++ b/tests/DCC/MeasurementResults.MeasurementResult.MeasuringEquipments.test.ts @@ -0,0 +1,58 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +import { select, toTextArr, toTextContentArr } from "../util"; +import { DCCDocument, MeasuringEquipmentType } from "../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:measuringEquipments/dcc:measuringEquipment[1]"; +const xpath = { + measuringEquipments: { + measuringEquipment: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + identifications: { + identification: { + issuer: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:value)`, + }, + }, + refType: `string(${base}//@refType)`, + }, + }, +}; + +describe("MeasuringEquipmentType", () => { + let dcc: DCCDocument, measuringEquipment: MeasuringEquipmentType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + measuringEquipment = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].measuringEquipments.measuringEquipment[0]; + }); + + test("should get correct measurement result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measuringEquipments.measuringEquipment.name.content, dom); + expect(toTextArr(measuringEquipment.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct measuring equipment 1 identification issuer from XML", () => { + expect(measuringEquipment.identifications.identification[0].issuer._text).toBe( + select(xpath.measuringEquipments.measuringEquipment.identifications.identification.issuer, dom), + ); + }); + + test("should get correct measuring equipment 1 identification value from XML", () => { + expect(measuringEquipment.identifications.identification[0].value._text).toBe( + select(xpath.measuringEquipments.measuringEquipment.identifications.identification.value, dom), + ); + }); + + test("should get correct measuring equipment 1 refType from XML", () => { + expect(measuringEquipment._attr.refType).toBe(select(xpath.measuringEquipments.measuringEquipment.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/MeasurementResults.MeasurementResult.Name.test.ts b/tests/DCC/MeasurementResults.MeasurementResult.Name.test.ts new file mode 100644 index 0000000..1828f27 --- /dev/null +++ b/tests/DCC/MeasurementResults.MeasurementResult.Name.test.ts @@ -0,0 +1,35 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +import { select, toTextArr, toTextContentArr } from "../util"; +import { DCCDocument, MeasurementResultType } from "../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults"; +const xpath = { + measurementResults: { + measurementResult: { + name: { + content: `${base}/dcc:measurementResult[1]/dcc:name/dcc:content`, + }, + }, + }, +}; + +describe("MeasurementResultType", () => { + let dcc: DCCDocument, measurementResult: MeasurementResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + measurementResult = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0]; + }); + + test("should get correct measurement result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.name.content, dom); + expect(toTextArr(measurementResult.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/MeasurementResults.MeasurementResult.Results.test.ts b/tests/DCC/MeasurementResults.MeasurementResult.Results.test.ts new file mode 100644 index 0000000..64536b7 --- /dev/null +++ b/tests/DCC/MeasurementResults.MeasurementResult.Results.test.ts @@ -0,0 +1,302 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +import { select, toTextArr, toTextContentArr } from "../util"; +import { DCCDocument, ResultType } from "../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:results"; +const xpath = { + measurementResults: { + measurementResult: { + results: { + result: { + name: { + content: `${base}/dcc:result[1]/dcc:name/dcc:content`, + }, + data: { + list: { + quantity1: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + measurementMetaData: { + metaData: { + declaration: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:declaration/dcc:content`, + }, + data: { + quantity: { + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData/dcc:data/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:measurementMetaData/dcc:metaData//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]//@refType)`, + }, + quantity2: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/dcc:name/dcc:content`, + }, + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[2]//@refType)`, + }, + quantity3: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/dcc:name/dcc:content`, + }, + si_realListXMLList: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:unitXMLList)`, + si_expandedUncXMLList: { + si_uncertaintyXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:uncertaintyXMLList)`, + si_coverageFactorXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:coverageFactorXMLList)`, + si_coverageProbabilityXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:coverageProbabilityXMLList)`, + si_distributionXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/si:realListXMLList[1]/si:expandedUncXMLList/si:distributionXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[3]/@refType)`, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]//@refType)`, + }, + }, + }, + }, +}; + +describe("ResultType", () => { + let dcc: DCCDocument, result: ResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + result = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].results.result[0]; + }); + + test("should get correct result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.name.content, dom); + expect(toTextArr(result.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 1 hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 1 hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 1 hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 1 hybrid si:unitXMLList 2: from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 1 meta data declaration content from XML", () => { + // get expected list from example xml + const expected = <Element[]>( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.declaration.content, dom) + ); + expect(toTextArr(result.data.list[0].quantity[0].measurementMetaData.metaData[0].declaration.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 1 meta data hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0].data.quantity[0].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.data.quantity.si_hybrid.si_realListXMLList1 + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 1 meta data hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0].data.quantity[0].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.data.quantity.si_hybrid.si_realListXMLList1 + .si_unitXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 1 meta data hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0].data.quantity[0].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.data.quantity.si_hybrid.si_realListXMLList2 + .si_valueXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 1 meta data hybrid si:unitXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0].data.quantity[0].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 2 hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 2 hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 2 hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 2 hybrid si:unitXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[1].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 3 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.name.content, dom); + expect(toTextArr(result.data.list[0].quantity[2].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity 3 si:valueXMLList from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity 3 si:unitXMLList from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity 3 uncertainty list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.uncertaintyXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_uncertaintyXMLList, dom), + ); + }); + + test("should get correct result quantity 3 uncertainty coverage factor list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.coverageFactorXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_coverageFactorXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 uncertainty coverage probability list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.coverageProbabilityXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_coverageProbabilityXMLList, + dom, + ), + ); + }); + + test("should get correct result quantity 3 uncertainty distribution list from XML", () => { + expect(result.data.list[0].quantity[2].realListXMLList.expandedUncXMLList.distributionXMLList._text).toBe( + select( + xpath.measurementResults.measurementResult.results.result.data.list.quantity3.si_realListXMLList.si_expandedUncXMLList.si_distributionXMLList, + dom, + ), + ); + }); + + test("should get correct result refType from XML", () => { + expect(result._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.refType, dom)); + }); + + test("should get correct result data list refType from XML", () => { + expect(result.data.list[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.list.refType, dom)); + }); + + test("should get correct result quantity 1 refType from XML", () => { + expect(result.data.list[0].quantity[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.refType, dom), + ); + }); + + test("should get correct result quantity 1 meta data refType from XML", () => { + expect(result.data.list[0].quantity[0].measurementMetaData.metaData[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity1.measurementMetaData.metaData.refType, dom), + ); + }); + + test("should get correct result quantity 2 refType from XML", () => { + expect(result.data.list[0].quantity[1]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity2.refType, dom), + ); + }); + + test("should get correct result quantity 3 refType from XML", () => { + expect(result.data.list[0].quantity[2]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity3.refType, dom), + ); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/MeasurementResults.MeasurementResult.UsedMethods.test.ts b/tests/DCC/MeasurementResults.MeasurementResult.UsedMethods.test.ts new file mode 100644 index 0000000..54cdf56 --- /dev/null +++ b/tests/DCC/MeasurementResults.MeasurementResult.UsedMethods.test.ts @@ -0,0 +1,81 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +import { select, toTextArr, toTextContentArr } from "../util"; +import { DCCDocument, MeasurementResultType, UsedMethodListType, UsedMethodType } from "../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]"; +const xpath = { + measurementResults: { + measurementResult: { + usedMethods: { + usedMethod1: { + name: { + content: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:name/dcc:content`, + }, + description: { + content: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:description/dcc:content`, + contentDE: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:description/dcc:content[@lang='de']`, + contentEN: `${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:description/dcc:content[@lang='en']`, + }, + norm: `string(${base}/dcc:usedMethods/dcc:usedMethod[1]/dcc:norm[1])`, + refType: `string(${base}/dcc:usedMethods/dcc:usedMethod[1]//@refType)`, + }, + usedMethod2: { + name: { + content: `${base}/dcc:usedMethods/dcc:usedMethod[2]/dcc:name/dcc:content`, + }, + norm: `string(${base}/dcc:usedMethods/dcc:usedMethod[2]/dcc:norm[1])`, + refType: `string(${base}/dcc:usedMethods/dcc:usedMethod[2]//@refType)`, + }, + }, + }, + }, +}; + +describe("UsedMethodListType", () => { + let dcc: DCCDocument, usedMethods: UsedMethodListType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + usedMethods = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].usedMethods; + }); + + test("should get correct used method 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.name.content, dom); + expect(toTextArr(usedMethods.usedMethod[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct used method 1 description content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.description.content, dom); + expect(toTextArr(usedMethods.usedMethod[0].description.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct used method 1 norm from XML", () => { + expect(usedMethods.usedMethod[0].norm[0]._text).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.norm, dom)); + }); + + test("should get correct used method 1 refType from XML", () => { + expect(usedMethods.usedMethod[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod1.refType, dom)); + }); + + test("should get correct used method 2 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.usedMethods.usedMethod2.name.content, dom); + expect(toTextArr(usedMethods.usedMethod[1].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct used method 2 norm from XML", () => { + expect(usedMethods.usedMethod[1].norm[0]._text).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod2.norm, dom)); + }); + + test("should get correct used method 2 refType from XML", () => { + expect(usedMethods.usedMethod[1]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.usedMethods.usedMethod2.refType, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/Test_DCC_Minimal/AdministrativeData.CalibrationLaboratory.test.ts b/tests/DCC/Test_DCC_Minimal/AdministrativeData.CalibrationLaboratory.test.ts new file mode 100644 index 0000000..3529e3b --- /dev/null +++ b/tests/DCC/Test_DCC_Minimal/AdministrativeData.CalibrationLaboratory.test.ts @@ -0,0 +1,34 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/Test_DCC_Minimal.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { CalibrationLaboratoryType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:calibrationLaboratory/dcc:contact"; +const xpath = { + name: `string(${base}/dcc:name/dcc:content)`, + location: { + city: `${base}/dcc:location/dcc:city`, + }, +}; + +describe("Test_DCC_Minimal: CalibrationLaboratoryType", () => { + let dcc: DCCDocument, calibrationLaboratory: CalibrationLaboratoryType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + calibrationLaboratory = dcc.digitalCalibrationCertificate.administrativeData.calibrationLaboratory; + }); + + test("should get correct name from XML", () => { + expect(calibrationLaboratory.contact.name.content[0]._text).toBe(select(xpath.name, dom)); + }); + + test("should get correct city from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.city, dom); + expect(toTextArr(calibrationLaboratory.contact.location.city)).toEqual(toTextContentArr(expected)); + }); +}); diff --git a/tests/DCC/Test_DCC_Minimal/AdministrativeData.CoreDataType.test.ts b/tests/DCC/Test_DCC_Minimal/AdministrativeData.CoreDataType.test.ts new file mode 100644 index 0000000..e9ca47c --- /dev/null +++ b/tests/DCC/Test_DCC_Minimal/AdministrativeData.CoreDataType.test.ts @@ -0,0 +1,116 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/Test_DCC_Minimal.xml + */ + +import * as fc from "fast-check"; +import { indexOf, select, toTextArr, toTextContentArr } from "../../util"; +import { CoreDataType, DCCDocument, DCCXMLElement } from "../../../src"; +import { string_ISO639_1 } from "../../Arbitraries"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:coreData"; +const xpath = { + coreData: { + countryCodeISO3166_1: `string(${base}/dcc:countryCodeISO3166_1)`, + usedLangCodeISO639_1: `${base}/dcc:usedLangCodeISO639_1`, + mandatoryLangCodeISO639_1: `${base}/dcc:mandatoryLangCodeISO639_1`, + uniqueIdentifier: `string(${base}/dcc:uniqueIdentifier)`, + identifications: { + identification: { + issuer: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + }, + beginPerformanceDate: `string(${base}/dcc:beginPerformanceDate)`, + endPerformanceDate: `string(${base}/dcc:endPerformanceDate)`, + performanceLocation: `string(${base}/dcc:performanceLocation)`, + }, +}; + +describe("Test_DCC_Minimal: CoreDataType", () => { + let dcc: DCCDocument, coreData: CoreDataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + coreData = dcc.digitalCalibrationCertificate.administrativeData.coreData; + }); + + test("should get correct countryCodeISO3166_1 from XML", () => { + expect(coreData.countryCodeISO3166_1._text).toBe(select(xpath.coreData.countryCodeISO3166_1, dom)); + }); + + test("should get correct usedLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom); + expect(toTextArr(coreData.usedLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct mandatoryLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.mandatoryLangCodeISO639_1, dom); + expect(toTextArr(coreData.mandatoryLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct unique identifier from XML", () => { + expect(coreData.uniqueIdentifier._text).toBe(select(xpath.coreData.uniqueIdentifier, dom)); + }); + + test("should get correct identification issuer from XML", () => { + expect(coreData.identifications.identification[0].issuer._text).toBe(select(xpath.coreData.identifications.identification.issuer, dom)); + }); + + test("should get correct identification value from XML", () => { + expect(coreData.identifications.identification[0].value._text).toBe(select(xpath.coreData.identifications.identification.value, dom)); + }); + + test("should get correct identification name content from XML", () => { + const expected = <Element[]>select(xpath.coreData.identifications.identification.name.content, dom); + expect(toTextArr(coreData.identifications.identification[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct begin performance date from XML", () => { + expect(coreData.beginPerformanceDate._text).toBe(select(xpath.coreData.beginPerformanceDate, dom)); + }); + test("should get correct end performance date from XML", () => { + expect(coreData.endPerformanceDate._text).toBe(select(xpath.coreData.endPerformanceDate, dom)); + }); + test("should get correct performance location from XML", () => { + expect(coreData.performanceLocation._text).toBe(select(xpath.coreData.performanceLocation, dom)); + }); + + /* test for setters */ + test("should set usedLangCodeISO639_1 correctly", () => { + fc.assert( + fc.property(string_ISO639_1(), (str) => { + // add new element to array + coreData.usedLangCodeISO639_1.push(new DCCXMLElement({ _text: str })); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).toContain(str); + expect(toTextContentArr(actual)).toContain(str); + }), + ); + }); + + test("should delete usedLangCodeISO639_1 correctly", () => { + const selection = toTextContentArr(<Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom)); + fc.assert( + fc.property(fc.constantFrom(...selection), (str) => { + // get index and remove element from array + const index = indexOf(coreData.usedLangCodeISO639_1, str); + coreData.usedLangCodeISO639_1.splice(index, 1); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).not.toContain(str); + expect(toTextContentArr(actual)).not.toContain(str); + }), + ); + }); +}); diff --git a/tests/DCC/Test_DCC_Minimal/AdministrativeData.Customer.test.ts b/tests/DCC/Test_DCC_Minimal/AdministrativeData.Customer.test.ts new file mode 100644 index 0000000..3888155 --- /dev/null +++ b/tests/DCC/Test_DCC_Minimal/AdministrativeData.Customer.test.ts @@ -0,0 +1,42 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/Test_DCC_Minimal.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { ContactType, DCCDocument, LocationType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:customer"; +const xpath = { + customer: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + location: { + city: `${base}/dcc:location/dcc:city[1]`, + }, + }, +}; + +describe("Test_DCC_Minimal: ContactType", () => { + let dcc: DCCDocument, customer: ContactType, location: LocationType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + customer = dcc.digitalCalibrationCertificate.administrativeData.customer; + location = customer.location; /* TODO: check iff this variable is used anywhere */ + }); + + test("should get correct customer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.customer.name.content, dom); + expect(toTextArr(customer.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct customer location city from XML", () => { + const expected = <Element[]>select(xpath.customer.location.city, dom); + expect(customer.location.city[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/Test_DCC_Minimal/AdministrativeData.Items.test.ts b/tests/DCC/Test_DCC_Minimal/AdministrativeData.Items.test.ts new file mode 100644 index 0000000..958427c --- /dev/null +++ b/tests/DCC/Test_DCC_Minimal/AdministrativeData.Items.test.ts @@ -0,0 +1,64 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/Test_DCC_Minimal.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { ItemType, DCCDocument, IdentificationType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:items"; +const xpath = { + items: { + item: { + name: { + content: `${base}/dcc:item[1]/dcc:name/dcc:content`, + }, + manufacturer: { + name: { + content: `${base}/dcc:item[1]/dcc:manufacturer/dcc:name/dcc:content`, + }, + }, + identifications: { + identification: { + issuer: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:item[1]/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + }, + }, + }, +}; + +describe("Test_DCC_Minimal: ItemType", () => { + let dcc: DCCDocument, item: ItemType, identification: IdentificationType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + item = dcc.digitalCalibrationCertificate.administrativeData.items.item[0]; + identification = item.identifications.identification[0]; + }); + + test("should get correct item name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.name.content, dom); + expect(toTextArr(item.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct item manufacturer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.items.item.manufacturer.name.content, dom); + expect(toTextArr(item.manufacturer.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct identification issuer from XML", () => { + expect(identification.issuer._text).toBe(select(xpath.items.item.identifications.identification.issuer, dom)); + }); + + test("should get correct identification value from XML", () => { + expect(identification.value._text).toBe(select(xpath.items.item.identifications.identification.value, dom)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/Test_DCC_Minimal/AdministrativeData.RespPersons.test.ts b/tests/DCC/Test_DCC_Minimal/AdministrativeData.RespPersons.test.ts new file mode 100644 index 0000000..7c74d61 --- /dev/null +++ b/tests/DCC/Test_DCC_Minimal/AdministrativeData.RespPersons.test.ts @@ -0,0 +1,37 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/Test_DCC_Minimal.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { RespPersonType, DCCDocument } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:respPersons"; +const xpath = { + respPersons: { + respPerson: { + person: { + name: { + content: `${base}/dcc:respPerson[1]/dcc:person/dcc:name/dcc:content`, + }, + }, + }, + }, +}; + +describe("Test_DCC_Minimal: RespPersonType", () => { + let dcc: DCCDocument, respPerson: RespPersonType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + respPerson = dcc.digitalCalibrationCertificate.administrativeData.respPersons.respPerson[0]; + }); + + test("should get correct responsible person 1 name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.respPersons.respPerson.person.name.content, dom); + expect(toTextArr(respPerson.person.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/Test_DCC_Minimal/AdministrativeData.SoftwareListType.test.ts b/tests/DCC/Test_DCC_Minimal/AdministrativeData.SoftwareListType.test.ts new file mode 100644 index 0000000..3577e44 --- /dev/null +++ b/tests/DCC/Test_DCC_Minimal/AdministrativeData.SoftwareListType.test.ts @@ -0,0 +1,41 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/Test_DCC_Minimal.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { SoftwareListType, DCCDocument, SoftwareType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:dccSoftware/dcc:software"; +const xpath = { + software: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + release: `string(${base}/dcc:release)`, + type: `string(${base}/dcc:type)`, + description: `${base}/dcc:description`, + _id: `${base}/@id`, + _refType: `${base}/@refType`, + }, +}; + +describe("Test_DCC_Minimal: DccSoftwareType", () => { + let dcc: DCCDocument, dccSoftware: SoftwareListType, software: SoftwareType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + dccSoftware = dcc.digitalCalibrationCertificate.administrativeData.dccSoftware; + software = dccSoftware.software[0]; + }); + + test("should get correct software name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.software.name.content, dom); + expect(toTextArr(software.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct software release version of software from XML", () => { + expect(software.release._text).toBe(select(xpath.software.release, dom)); + }); +}); diff --git a/tests/DCC/Test_DCC_Minimal/DigitalCalibrationCertificateType.test.ts b/tests/DCC/Test_DCC_Minimal/DigitalCalibrationCertificateType.test.ts new file mode 100644 index 0000000..1f0006a --- /dev/null +++ b/tests/DCC/Test_DCC_Minimal/DigitalCalibrationCertificateType.test.ts @@ -0,0 +1,21 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/Test_DCC_Minimal.xml + */ + +import { select } from "../../util"; + +const VERSION_XPATH = "string(/dcc:digitalCalibrationCertificate/@schemaVersion)"; + +describe("Test_DCC_Minimal: DigitalCalibrationCertificateType", () => { + let xml, dcc, dom; + + beforeEach(() => { + ({ xml, dcc, dom } = xmlEnv.recreateEnv()); + }); + + test("should get correct schemaVersion from XML", () => { + const expectedVersion = select(VERSION_XPATH, dom); + expect(dcc.digitalCalibrationCertificate._attr.schemaVersion).toBe(expectedVersion); + }); +}); diff --git a/tests/DCC/Test_DCC_Minimal/MeasurementResults.MeasurementResult.Name.test.ts b/tests/DCC/Test_DCC_Minimal/MeasurementResults.MeasurementResult.Name.test.ts new file mode 100644 index 0000000..bd50cc0 --- /dev/null +++ b/tests/DCC/Test_DCC_Minimal/MeasurementResults.MeasurementResult.Name.test.ts @@ -0,0 +1,35 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/Test_DCC_Minimal.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, MeasurementResultType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults"; +const xpath = { + measurementResults: { + measurementResult: { + name: { + content: `${base}/dcc:measurementResult[1]/dcc:name/dcc:content`, + }, + }, + }, +}; + +describe("Test_DCC_Minimal: MeasurementResultType", () => { + let dcc: DCCDocument, measurementResult: MeasurementResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + measurementResult = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0]; + }); + + test("should get correct measurement result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.name.content, dom); + expect(toTextArr(measurementResult.name.content)).toEqual(toTextContentArr(expected)); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/Test_DCC_Minimal/MeasurementResults.MeasurementResult.Results.test.ts b/tests/DCC/Test_DCC_Minimal/MeasurementResults.MeasurementResult.Results.test.ts new file mode 100644 index 0000000..06a0973 --- /dev/null +++ b/tests/DCC/Test_DCC_Minimal/MeasurementResults.MeasurementResult.Results.test.ts @@ -0,0 +1,100 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/Test_DCC_Minimal.xml + */ + +import { select, toTextArr, toTextContentArr } from "../../util"; +import { DCCDocument, ResultType } from "../../../src"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:measurementResults/dcc:measurementResult[1]/dcc:results"; +const xpath = { + measurementResults: { + measurementResult: { + results: { + result: { + name: { + content: `${base}/dcc:result[1]/dcc:name/dcc:content`, + }, + data: { + list: { + quantity: { + name: { + content: `${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/dcc:name/dcc:content`, + }, + si_hybrid: { + si_realListXMLList1: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[1]/si:unitXMLList)`, + }, + si_realListXMLList2: { + si_valueXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:valueXMLList)`, + si_unitXMLList: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]/si:hybrid/si:realListXMLList[2]/si:unitXMLList)`, + }, + }, + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list/dcc:quantity[1]//@refType)`, + }, + + refType: `string(${base}/dcc:result[1]/dcc:data/dcc:list//@refType)`, + }, + }, + refType: `string(${base}/dcc:result[1]//@refType)`, + }, + }, + }, + }, +}; + +describe("Test_DCC_Minimal: ResultType", () => { + let dcc: DCCDocument, result: ResultType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + result = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].results.result[0]; + }); + + test("should get correct result name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.measurementResults.measurementResult.results.result.name.content, dom); + expect(toTextArr(result.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct result quantity hybrid si:valueXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity.si_hybrid.si_realListXMLList1.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity hybrid si:unitXMLList 1 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[0].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity.si_hybrid.si_realListXMLList1.si_unitXMLList, dom), + ); + }); + + test("should get correct result quantity hybrid si:valueXMLList 2 from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].valueXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity.si_hybrid.si_realListXMLList2.si_valueXMLList, dom), + ); + }); + + test("should get correct result quantity hybrid si:unitXMLList 2: from XML", () => { + expect(result.data.list[0].quantity[0].hybrid.realListXMLList[1].unitXMLList._text).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity.si_hybrid.si_realListXMLList2.si_unitXMLList, dom), + ); + }); + + test("should get correct result refType from XML", () => { + expect(result._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.refType, dom)); + }); + + test("should get correct result data list refType from XML", () => { + expect(result.data.list[0]._attr.refType).toBe(select(xpath.measurementResults.measurementResult.results.result.data.list.refType, dom)); + }); + + test("should get correct result quantity 1 refType from XML", () => { + expect(result.data.list[0].quantity[0]._attr.refType).toBe( + select(xpath.measurementResults.measurementResult.results.result.data.list.quantity.refType, dom), + ); + }); + + /* TODO: setters */ +}); diff --git a/tests/DCC/common/AdministrativeData/CalibrationLaboratory.ts b/tests/DCC/common/AdministrativeData/CalibrationLaboratory.ts new file mode 100644 index 0000000..25a455d --- /dev/null +++ b/tests/DCC/common/AdministrativeData/CalibrationLaboratory.ts @@ -0,0 +1,78 @@ +import { select, toTextArr, toTextContentArr } from "../../../util"; +import { CalibrationLaboratoryType, DCCDocument } from "../../../../src"; +import { testRichContentType } from "../Types/RichContentType"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:calibrationLaboratory/dcc:contact"; +const xpath = { + name: `${base}/dcc:name`, + eMail: `string(${base}/dcc:eMail)`, + phone: `string(${base}/dcc:phone)`, + fax: `string(${base}/dcc:fax)`, + location: { + city: `${base}/dcc:location/dcc:city`, + countryCode: `${base}/dcc:location/dcc:countryCode`, + postCode: `${base}/dcc:location/dcc:postCode`, + street: `${base}/dcc:location/dcc:street`, + streetNo: `${base}/dcc:location/dcc:streetNo`, + further: `${base}/dcc:location/dcc:further/dcc:content`, + }, +}; + +export const testCalibrationLaboratory = () => { + describe("CalibrationLaboratoryType", () => { + let dcc: DCCDocument, calibrationLaboratory: CalibrationLaboratoryType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + calibrationLaboratory = dcc.digitalCalibrationCertificate.administrativeData.calibrationLaboratory; + }); + + test("should get correct name from XML", () => { + testRichContentType(xpath.name, calibrationLaboratory.contact.name, dom); + }); + + test("should get correct eMail from XML", () => { + expect(calibrationLaboratory.contact.eMail._text).toBe(select(xpath.eMail, dom)); + }); + + test("should get correct phone from XML", () => { + expect(calibrationLaboratory.contact.phone._text).toBe(select(xpath.phone, dom)); + }); + + test("should get correct city from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.city, dom); + expect(toTextArr(calibrationLaboratory.contact.location.city)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct countryCode from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.countryCode, dom); + expect(toTextArr(calibrationLaboratory.contact.location.countryCode)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct postCode from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.postCode, dom); + expect(toTextArr(calibrationLaboratory.contact.location.postCode)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct street from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.street, dom); + expect(toTextArr(calibrationLaboratory.contact.location.street)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct streetNo from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.streetNo, dom); + expect(toTextArr(calibrationLaboratory.contact.location.streetNo)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct further element from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.location.further, dom); + expect(toTextArr(calibrationLaboratory.contact.location.further[0].content)).toEqual(toTextContentArr(expected)); + }); + }); +}; diff --git a/tests/DCC/common/AdministrativeData/CoreDataType.ts b/tests/DCC/common/AdministrativeData/CoreDataType.ts new file mode 100644 index 0000000..ea974a5 --- /dev/null +++ b/tests/DCC/common/AdministrativeData/CoreDataType.ts @@ -0,0 +1,117 @@ +import * as fc from "fast-check"; +import { indexOf, select, toTextArr, toTextContentArr } from "../../../util"; +import { CoreDataType, DCCDocument, DCCXMLElement } from "../../../../src"; +import { string_ISO639_1 } from "../../../Arbitraries"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:coreData"; +const xpath = { + coreData: { + countryCodeISO3166_1: `string(${base}/dcc:countryCodeISO3166_1)`, + usedLangCodeISO639_1: `${base}/dcc:usedLangCodeISO639_1`, + mandatoryLangCodeISO639_1: `${base}/dcc:mandatoryLangCodeISO639_1`, + uniqueIdentifier: `string(${base}/dcc:uniqueIdentifier)`, + identifications: { + identification: { + issuer: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:issuer)`, + value: `string(${base}/dcc:identifications/dcc:identification[1]/dcc:value)`, + name: { + content: `${base}/dcc:identifications/dcc:identification[1]/dcc:name/dcc:content`, + }, + }, + }, + receiptDate: `string(${base}/dcc:receiptDate)`, + beginPerformanceDate: `string(${base}/dcc:beginPerformanceDate)`, + endPerformanceDate: `string(${base}/dcc:endPerformanceDate)`, + performanceLocation: `string(${base}/dcc:performanceLocation)`, + }, +}; + +export const testCoreData = () => { + describe("CoreDataType", () => { + let dcc: DCCDocument, coreData: CoreDataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + coreData = dcc.digitalCalibrationCertificate.administrativeData.coreData; + }); + + test("should get correct countryCodeISO3166_1 from XML", () => { + expect(coreData.countryCodeISO3166_1._text).toBe(select(xpath.coreData.countryCodeISO3166_1, dom)); + }); + + test("should get correct usedLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom); + expect(toTextArr(coreData.usedLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct mandatoryLangCodeISO639_1 from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.coreData.mandatoryLangCodeISO639_1, dom); + expect(toTextArr(coreData.mandatoryLangCodeISO639_1)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct unique identifier from XML", () => { + expect(coreData.uniqueIdentifier._text).toBe(select(xpath.coreData.uniqueIdentifier, dom)); + }); + + test("should get correct identification issuer from XML", () => { + expect(coreData.identifications.identification[0].issuer._text).toBe(select(xpath.coreData.identifications.identification.issuer, dom)); + }); + + test("should get correct identification value from XML", () => { + expect(coreData.identifications.identification[0].value._text).toBe(select(xpath.coreData.identifications.identification.value, dom)); + }); + + test("should get correct identification name content from XML", () => { + const expected = <Element[]>select(xpath.coreData.identifications.identification.name.content, dom); + expect(toTextArr(coreData.identifications.identification[0].name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct receipt date from XML", () => { + expect(coreData.receiptDate._text).toBe(select(xpath.coreData.receiptDate, dom)); + }); + test("should get correct begin performance date from XML", () => { + expect(coreData.beginPerformanceDate._text).toBe(select(xpath.coreData.beginPerformanceDate, dom)); + }); + test("should get correct end performance date from XML", () => { + expect(coreData.endPerformanceDate._text).toBe(select(xpath.coreData.endPerformanceDate, dom)); + }); + test("should get correct performance location from XML", () => { + expect(coreData.performanceLocation._text).toBe(select(xpath.coreData.performanceLocation, dom)); + }); + + /* test for setters */ + test("should set usedLangCodeISO639_1 correctly", () => { + fc.assert( + fc.property(string_ISO639_1(), (str) => { + // add new element to array + coreData.usedLangCodeISO639_1.push(new DCCXMLElement({ _text: str })); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).toContain(str); + expect(toTextContentArr(actual)).toContain(str); + }), + ); + }); + + test("should delete usedLangCodeISO639_1 correctly", () => { + const selection = toTextContentArr(<Element[]>select(xpath.coreData.usedLangCodeISO639_1, dom)); + fc.assert( + fc.property(fc.constantFrom(...selection), (str) => { + // get index and remove element from array + const index = indexOf(coreData.usedLangCodeISO639_1, str); + coreData.usedLangCodeISO639_1.splice(index, 1); + + // get actual list from xml + const actual = <Element[]>select(xpath.coreData.usedLangCodeISO639_1, dcc); + + expect(toTextArr(coreData.usedLangCodeISO639_1)).not.toContain(str); + expect(toTextContentArr(actual)).not.toContain(str); + }), + ); + }); + }); +}; diff --git a/tests/DCC/common/AdministrativeData/RespPersons.ts b/tests/DCC/common/AdministrativeData/RespPersons.ts new file mode 100644 index 0000000..88495a0 --- /dev/null +++ b/tests/DCC/common/AdministrativeData/RespPersons.ts @@ -0,0 +1,19 @@ +import { select } from "../../../util"; +import { testRespPersonType } from "../Types/RespPersonType"; + +const base = "/dcc:digitalCalibrationCertificate/dcc:administrativeData/dcc:respPersons"; +const xpath = { + respPerson: `${base}/dcc:respPerson`, +}; +export const testRespPersonListType = () => { + describe("RespPersonListType", () => { + const { dom } = xmlEnv.recreateEnv(); + + const expectedRespPersons = <Element[]>select(xpath.respPerson, dom); + for (let i = 0; i < expectedRespPersons.length; i++) { + testRespPersonType(`${xpath.respPerson}[${i + 1}]`, (dcc) => dcc.digitalCalibrationCertificate.administrativeData.respPersons.respPerson[i]); + } + + /* TODO: setters */ + }); +}; diff --git a/tests/DCC/common/Types/ContactType.ts b/tests/DCC/common/Types/ContactType.ts new file mode 100644 index 0000000..07b0d21 --- /dev/null +++ b/tests/DCC/common/Types/ContactType.ts @@ -0,0 +1,72 @@ +import { ContactNotStrictType, ContactType, DCCDocument } from "../../../../src"; +import { select, toTextArr, toTextContentArr, undefinedIfEmpty } from "../../../util"; + +export const testContactType = (base: string, contactTypeFn: (dcc: DCCDocument) => ContactType | ContactNotStrictType) => { + const xpath = { + customer: { + name: { + content: `${base}/dcc:name/dcc:content`, + }, + email: `string(${base}/dcc:eMail)`, + phone: `string(${base}/dcc:phone)`, + fax: `string(${base}/dcc:fax)`, + location: { + city: `${base}/dcc:location/dcc:city[1]`, + countryCode: `${base}/dcc:location/dcc:countryCode[1]`, + postCode: `${base}/dcc:location/dcc:postCode[1]`, + postBoxOffice: `${base}/dcc:location/dcc:postBoxOffice[1]`, + state: `${base}/dcc:location/dcc:state[1]`, + street: `${base}/dcc:location/dcc:street[1]`, + streetNo: `${base}/dcc:location/dcc:streetNo[1]`, + further: `${base}/dcc:location/dcc:further[1]/dcc:content`, + positionCoordinates: `${base}/dcc:location/dcc:positionCoordinates[1]`, + }, + descriptionData: `${base}/dcc:descriptionData`, + _id: `${base}/@id`, + }, + }; + + describe("ContactType", () => { + let dcc: DCCDocument, contactType: ContactType | ContactNotStrictType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + contactType = contactTypeFn(dcc); + }); + + test("should get correct customer name content from XML", () => { + // get expected list from example xml + const expected = <Element[]>select(xpath.customer.name.content, dom); + expect(toTextArr(contactType.name.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct customer email address from XML", () => { + expect(contactType.eMail?._text).toBe(undefinedIfEmpty(select(xpath.customer.email, dom))); + }); + + test("should get correct customer location city from XML", () => { + const expected = <Element[]>select(xpath.customer.location.city, dom); + expect(contactType.location?.city[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location county code from XML", () => { + const expected = <Element[]>select(xpath.customer.location.countryCode, dom); + expect(contactType.location?.countryCode[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location post code from XML", () => { + const expected = <Element[]>select(xpath.customer.location.postCode, dom); + expect(contactType.location?.postCode[0]._text).toEqual(toTextContentArr(expected)[0]); + }); + + test("should get correct customer location further from XML", () => { + const expected = <Element[]>select(xpath.customer.location.further, dom); + + for (let i = 0; i < expected.length; i++) { + expect(contactType.location?.further[0].content[i]._text).toBe(expected[i].textContent); + } + }); + + /* TODO: setters */ + }); +}; diff --git a/tests/DCC/common/Types/DataType.ts b/tests/DCC/common/Types/DataType.ts new file mode 100644 index 0000000..e39bb76 --- /dev/null +++ b/tests/DCC/common/Types/DataType.ts @@ -0,0 +1,23 @@ +import { DataType, DCCDocument } from "../../../../src"; +import { select, toTextArr, toTextContentArr, undefinedIfEmpty } from "../../../util"; + +export const testDataType = (base: string, dataTypeFn: (dcc: DCCDocument) => DataType) => { + const xpath = { + text: `${base}/dcc:text`, + quantity: `${base}/dcc:quantity`, + list: `${base}/dcc:list`, + }; + + describe("DataType", () => { + let dcc: DCCDocument, dataType: DataType, dom; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + dataType = dataTypeFn(dcc); + }); + + test("noop", () => {}); + + // TODO(Statement): quantity with real + }); +}; diff --git a/tests/DCC/common/Types/RespPersonType.ts b/tests/DCC/common/Types/RespPersonType.ts new file mode 100644 index 0000000..4284f9e --- /dev/null +++ b/tests/DCC/common/Types/RespPersonType.ts @@ -0,0 +1,28 @@ +import { DCCDocument, RespPersonType } from "../../../../src"; +import { select, undefinedIfEmpty } from "../../../util"; +import { testContactType } from "./ContactType"; + +export const testRespPersonType = (base: string, respPersonTypeFn: (dcc: DCCDocument) => RespPersonType) => { + const xpath = { + person: `${base}/dcc:person`, + mainSigner: `string(${base}/dcc:mainSigner)`, + }; + + describe("RespPersonType", () => { + let dcc: DCCDocument, respPersonType: RespPersonType, dom; + ({ dcc, dom } = xmlEnv.recreateEnv()); + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + respPersonType = respPersonTypeFn(dcc); + }); + + testContactType(xpath.person, (dcc) => respPersonTypeFn(dcc).person); + + test("should get correct responsible person main signer flag from XML", () => { + expect(respPersonType.mainSigner?._text).toBe(undefinedIfEmpty(select(xpath.mainSigner, dom))); + }); + + /* TODO: setters */ + }); +}; diff --git a/tests/DCC/common/Types/RichContentType.ts b/tests/DCC/common/Types/RichContentType.ts new file mode 100644 index 0000000..cf873f0 --- /dev/null +++ b/tests/DCC/common/Types/RichContentType.ts @@ -0,0 +1,25 @@ +import { JSDOM } from "jsdom"; +import * as _ from "lodash"; +import { RichContentType } from "../../../../src"; +import { select } from "../../../util"; + +const testContent = (base: string, richContent: RichContentType, dom: JSDOM) => { + const elements = <Element[]>select(`${base}/dcc:content`, dom); + // get expected langs from xml, filter out empty strings + const langs = _.uniq(elements.map((x) => x.getAttribute("lang")).filter((x) => x)); + if(langs.length > 0) { + // check content for each lang if there are any + for (const lang of langs) { + expect(richContent.getContent(lang)._text).toBe(select(`string(${base}/dcc:content[@lang="${lang}"])`, dom)); + } + } else { + // check content if there are no langs + expect(richContent.getContent()._text).toBe(select(`string(${base}/dcc:content)`, dom)); + } +} + +export const testRichContentType = (base: string, richContent: RichContentType, dom: JSDOM) => { + testContent(base, richContent, dom); + // TODO: test file + // TODO: test formula +}; diff --git a/tests/DCC/common/Types/StatementListType.ts b/tests/DCC/common/Types/StatementListType.ts new file mode 100644 index 0000000..254fda4 --- /dev/null +++ b/tests/DCC/common/Types/StatementListType.ts @@ -0,0 +1,18 @@ +import { select } from "../../../util"; +import { testStatementMetaDataType } from "./StatementMetaDataType"; +import { DCCDocument, StatementListType } from "../../../../src"; + +export const testStatementListType = (base, statementListTypeFn: (dcc: DCCDocument) => StatementListType) => { + const xpath = { + statement: `${base}/dcc:statement`, + }; + + describe("StatementListType", () => { + const { dom } = xmlEnv.recreateEnv(); + + const expectedStatements = <Element[]>select(xpath.statement, dom); + for (let i = 0; i < expectedStatements.length; i++) { + testStatementMetaDataType(i, `${xpath.statement}[${i + 1}]`, (dcc) => statementListTypeFn(dcc).statement[i]); + } + }); +}; diff --git a/tests/DCC/common/Types/StatementMetaDataType.ts b/tests/DCC/common/Types/StatementMetaDataType.ts new file mode 100644 index 0000000..5e09d86 --- /dev/null +++ b/tests/DCC/common/Types/StatementMetaDataType.ts @@ -0,0 +1,72 @@ +import { DCCDocument, StatementMetaDataType } from "../../../../src"; +import { select, toTextArr, toTextContentArr, undefinedIfEmpty } from "../../../util"; +import { testContactType } from "./ContactType"; +import { testDataType } from "./DataType"; + +export const testStatementMetaDataType = (name, base: string, statementMetaDataTypeFn: (dcc: DCCDocument) => StatementMetaDataType) => { + const xpath = { + norm: `${base}/dcc:norm`, + reference: `${base}/dcc:reference`, + declaration: { + content: `${base}/dcc:declaration/dcc:content`, + }, + conformity: `string(${base}/dcc:conformity)`, + date: `string(${base}/dcc:date)`, + respAuthority: `${base}/dcc:respAuthority`, + data: `${base}/dcc:data`, + + refType: `string(${base}/@refType)`, + }; + + describe(`StatementMetaDataType ${name}`, () => { + let dcc: DCCDocument, statementMetaDataType: StatementMetaDataType, dom; + ({ dcc, dom } = xmlEnv.recreateEnv()); + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + statementMetaDataType = statementMetaDataTypeFn(dcc); + }); + + const hasContact = <boolean>select(`boolean(${xpath.respAuthority})`, dom); + if (hasContact) { + testContactType(xpath.respAuthority, (dcc) => statementMetaDataTypeFn(dcc).respAuthority); + } + + const hasData = <boolean>select(`boolean(${xpath.data})`, dom); + if (hasData) { + testDataType(xpath.data, (dcc) => statementMetaDataTypeFn(dcc).data); + } + + test("should get correct statement declaration content from XML", () => { + const expected = <Element[]>select(xpath.declaration.content, dom); + expect(toTextArr(statementMetaDataType.declaration?.content)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement norm model from XML", () => { + const expected = <Element[]>select(xpath.norm, dom); + expect(toTextArr(statementMetaDataType.norm)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement reference from XML", () => { + const expected = <Element[]>select(xpath.reference, dom); + expect(toTextArr(statementMetaDataType.reference)).toEqual(toTextContentArr(expected)); + }); + + test("should get correct statement refType from XML", () => { + const expected = select(xpath.refType, dom); + expect(statementMetaDataType._attr.refType).toBe(undefinedIfEmpty(expected)); + }); + + test("should get correct statement conformity from XML", () => { + const expected = select(xpath.conformity, dom); + expect(statementMetaDataType.conformity?._text).toBe(undefinedIfEmpty(expected)); + }); + + test("should get correct statement date from XML", () => { + const expected = select(xpath.date, dom); + expect(statementMetaDataType.date?._text).toBe(undefinedIfEmpty(expected)); + }); + + /* TODO: setters */ + }); +}; diff --git a/tests/DCCDocument.test.ts b/tests/DCCDocument.test.ts index 3e1d889..06dccbf 100644 --- a/tests/DCCDocument.test.ts +++ b/tests/DCCDocument.test.ts @@ -1,12 +1,20 @@ -import { DCCDocument } from "../src"; -import { xml } from "./Resources/example.xml"; -import { expect } from "chai"; -import { describe, it } from "mocha"; - -describe("DCCDocument", - () => { - it("should not modify XML", () => { - let dcc = DCCDocument.fromXml(xml); - expect(dcc.toXML()).to.be.equal(xml); - }); +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/example.xml + */ + +describe("DCCDocument", () => { + let xml, dcc; + + beforeEach(() => { + ({ xml, dcc } = xmlEnv.recreateEnv()); + }); + + test("fromXml() and toXml() should not modify XML", () => { + // fix line endings, they are always LF + xml = xml.replace(/\r\n|\r|\n/g, "\n"); + + // fromXml() is part of the XMLEnvironment + expect(dcc.toXML()).toBe(xml); }); +}); diff --git a/tests/GP_Temperature/CharsXMLList.test.ts b/tests/GP_Temperature/CharsXMLList.test.ts new file mode 100644 index 0000000..ac10b24 --- /dev/null +++ b/tests/GP_Temperature/CharsXMLList.test.ts @@ -0,0 +1,25 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select } from "../util"; +import { DCCDocument } from "../../src"; + +const base = "//dcc:quantity[@refType='test_charsXMLList']"; +const xpath = { + charsXMLList: `string(${base}/dcc:charsXMLList)`, +}; + +describe("CharsXMLList", () => { + let dcc: DCCDocument, dom, result; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + result = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].results.result[0]; + }); + + test("should get correct charsXMLList from XML", () => { + expect(result.data.quantity[1].charsXMLList._text).toBe(select(xpath.charsXMLList, dom)); + }); +}); diff --git a/tests/GP_Temperature/noQuantity.test.ts b/tests/GP_Temperature/noQuantity.test.ts new file mode 100644 index 0000000..8b8bc09 --- /dev/null +++ b/tests/GP_Temperature/noQuantity.test.ts @@ -0,0 +1,56 @@ +/** + * @jest-environment ./tests/XMLEnvironment.ts + * @xml ./tests/resources/GP_Temperature_v3.2.0_DCC.xml + */ + +import { select, toTextArr, toTextContentArr } from "../util"; +import { DCCDocument } from "../../src"; + +const base = "//dcc:quantity[@refType='test_noQuantity']/dcc:noQuantity"; +const xpath = { + noQuantity: { + name: { + content: `string(${base}/dcc:name/dcc:content)`, + }, + content: `string(${base}/dcc:content)`, + file: { + fileName: `string(${base}/dcc:file/dcc:fileName)`, + mimeType: `string(${base}/dcc:file/dcc:mimeType)`, + dataBase64: `string(${base}/dcc:file/dcc:dataBase64)`, + }, + formula: { + latex: `string(${base}/dcc:formula/dcc:latex)`, + }, + }, +}; + +describe("noQuantity", () => { + let dcc: DCCDocument, dom, result; + + beforeEach(() => { + ({ dcc, dom } = xmlEnv.recreateEnv()); + result = dcc.digitalCalibrationCertificate.measurementResults.measurementResult[0].results.result[0]; + }); + + test("should get correct name from XML", () => { + const expected = <Element[]>select(xpath.noQuantity.name.content, dom); + + expect(toTextArr(result.data.quantity[0].noQuantity.name.content)[0]).toBe(expected); + }); + + test("should get correct content from XML", () => { + expect(result.data.quantity[0].noQuantity.content[0]._text).toBe(select(xpath.noQuantity.content, dom)); + }); + + test("should get correct fileName from XML", () => { + expect(result.data.quantity[0].noQuantity.file[0].fileName._text).toBe(select(xpath.noQuantity.file.fileName, dom)); + }); + + test("should get correct mimeType from XML", () => { + expect(result.data.quantity[0].noQuantity.file[0].mimeType._text).toBe(select(xpath.noQuantity.file.mimeType, dom)); + }); + + test("should get correct latex formula from XML", () => { + expect(result.data.quantity[0].noQuantity.formula[0].latex._text).toBe(select(xpath.noQuantity.formula.latex, dom)); + }); +}); diff --git a/tests/XMLEnvironment.ts b/tests/XMLEnvironment.ts new file mode 100644 index 0000000..10160de --- /dev/null +++ b/tests/XMLEnvironment.ts @@ -0,0 +1,44 @@ +import * as fs from "fs/promises"; +import { DCCDocument } from "../src"; +import NodeEnvironment from "jest-environment-node"; +import { JSDOM } from "jsdom"; + +export default class XMLEnvironment extends NodeEnvironment { + xmlPath: string; + xml: string; + + constructor(config, context) { + super(config, context); + const xmlPath = context.docblockPragmas["xml"]; + if (xmlPath && typeof xmlPath === "string") { + this.xmlPath = xmlPath; + } + } + + async setup() { + await super.setup(); + if (this.xmlPath) { + this.xml = await this.readFile(this.xmlPath); + } + this.global.xmlEnv = this; + } + + recreateEnv(): { xml: string; dcc: DCCDocument; dom: JSDOM } { + return { + xml: this.xml, + dcc: this.xml ? DCCDocument.fromXml(this.xml) : DCCDocument.createEmpty(), + dom: new JSDOM(this.xml, { contentType: "application/xml" }), + }; + } + + async readFile(path: string) { + // check if file exists + if ((await fs.stat(path)).isFile()) { + return await fs.readFile(path, { encoding: "utf-8" }); + } else { + throw new Error(`File ${path} does not exist.`); + } + } +} + +export const TestEnvironment = XMLEnvironment; diff --git a/tests/index.d.ts b/tests/index.d.ts new file mode 100644 index 0000000..facbc06 --- /dev/null +++ b/tests/index.d.ts @@ -0,0 +1,12 @@ +import XMLEnvironment from "./XMLEnvironment"; + +declare let xmlEnv: XMLEnvironment; + +declare global { + let xmlEnv: XMLEnvironment; + namespace NodeJS { + interface Global { + xmlEnv: XMLEnvironment; + } + } +} diff --git a/tests/resources/GP_Temperature_Simplified.xml b/tests/resources/GP_Temperature_Simplified.xml new file mode 100644 index 0000000..7d299d4 --- /dev/null +++ b/tests/resources/GP_Temperature_Simplified.xml @@ -0,0 +1,352 @@ +<?xml version="1.0" encoding="utf-8"?> +<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dcc="https://ptb.de/dcc" xmlns:si="https://ptb.de/si" xsi:schemaLocation="https://ptb.de/dcc https://ptb.de/dcc/v3.2.0/dcc.xsd" schemaVersion="3.2.0"> + <dcc:administrativeData> + <dcc:dccSoftware> + <dcc:software> + <dcc:name> + <dcc:content>Notepad++ (32-bit)</dcc:content> + </dcc:name> + <dcc:release>v 8.2</dcc:release> + </dcc:software> + </dcc:dccSoftware> + <dcc:coreData> + <dcc:countryCodeISO3166_1>DE</dcc:countryCodeISO3166_1> + <dcc:usedLangCodeISO639_1>en</dcc:usedLangCodeISO639_1> + <dcc:usedLangCodeISO639_1>de</dcc:usedLangCodeISO639_1> + <dcc:mandatoryLangCodeISO639_1>en</dcc:mandatoryLangCodeISO639_1> + <dcc:uniqueIdentifier>GP_DCC_temperature_minimal_1.2</dcc:uniqueIdentifier> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>calibrationLaboratory</dcc:issuer> + <dcc:value>string-calibrationLaboratory-coreData</dcc:value> + <dcc:name> + <dcc:content lang="de">Auftrags Nr.</dcc:content> + <dcc:content lang="en">Order no.</dcc:content> + </dcc:name> + </dcc:identification> + </dcc:identifications> + <dcc:beginPerformanceDate>1957-08-13</dcc:beginPerformanceDate> + <dcc:endPerformanceDate>1957-08-13</dcc:endPerformanceDate> + <dcc:performanceLocation>laboratory</dcc:performanceLocation> + </dcc:coreData> + <dcc:items> + <dcc:item> + <dcc:name> + <dcc:content lang="de">Temperatur-Fühler</dcc:content> + <dcc:content lang="en">Temperature sensor</dcc:content> + </dcc:name> + <dcc:manufacturer> + <dcc:name> + <dcc:content>String</dcc:content> + </dcc:name> + </dcc:manufacturer> + <dcc:model>String</dcc:model> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>manufacturer</dcc:issuer> + <dcc:value>string-manufacturer-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Serien Nr.</dcc:content> + <dcc:content lang="en">Serial no.</dcc:content> + </dcc:name> + </dcc:identification> + <dcc:identification> + <dcc:issuer>customer</dcc:issuer> + <dcc:value>string-customer-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Messmittel Nr.</dcc:content> + <dcc:content lang="en">Measurement equipment no.</dcc:content> + </dcc:name> + </dcc:identification> + <dcc:identification> + <dcc:issuer>calibrationLaboratory</dcc:issuer> + <dcc:value>string-calibrationLaboratory-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Equipment Nr.</dcc:content> + <dcc:content lang="en">Equipment no.</dcc:content> + </dcc:name> + </dcc:identification> + </dcc:identifications> + </dcc:item> + </dcc:items> + <dcc:calibrationLaboratory> + <dcc:contact> + <dcc:name> + <dcc:content>Kalibrierfirma GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kalibrierfirma.xx</dcc:eMail> + <dcc:phone>+49 123 4567-89</dcc:phone> + <dcc:fax>+49 123 4567-90</dcc:fax> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + <dcc:street>Musterstraße</dcc:street> + <dcc:streetNo>1</dcc:streetNo> + <dcc:further> + <dcc:content>www.kalibrierfirma.xx</dcc:content> + </dcc:further> + </dcc:location> + </dcc:contact> + </dcc:calibrationLaboratory> + <dcc:respPersons> + <dcc:respPerson> + <dcc:person> + <dcc:name> + <dcc:content>Michaela Musterfrau</dcc:content> + </dcc:name> + </dcc:person> + <dcc:mainSigner>true</dcc:mainSigner> + </dcc:respPerson> + <dcc:respPerson> + <dcc:person> + <dcc:name> + <dcc:content>Michael Mustermann</dcc:content> + </dcc:name> + </dcc:person> + </dcc:respPerson> + </dcc:respPersons> + <dcc:customer> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + <dcc:further> + <dcc:content lang="de">Kunden Nr. 1024418</dcc:content> + <dcc:content lang="en">Customer ID no. 1024418</dcc:content> + </dcc:further> + </dcc:location> + </dcc:customer> + <dcc:statements> + <dcc:statement refType="basic_conformity"> + <dcc:declaration> + <dcc:content lang="de">Die Konformitätsaussage erfolgt anhand der Vorgaben des Kunden. Sie sind im DCC mit aufgeführt.</dcc:content> + <dcc:content lang="en">The conformity statement is made on the basis of the customer's specifications. They are listed in the DCC.</dcc:content> + </dcc:declaration> + <dcc:respAuthority> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + </dcc:location> + </dcc:respAuthority> + <dcc:conformity>pass</dcc:conformity> + </dcc:statement> + <dcc:statement refType="basic_recalibration"> + <dcc:declaration> + <dcc:content lang="de">Datum, wann nach der Festlegung durch den Kunden spätestens der Kalibriergegenstand rekalibriert werden soll:</dcc:content> + <dcc:content lang="en">Date when the calibration item is to be recalibrated at the latest according to the customer's specification:</dcc:content> + </dcc:declaration> + <dcc:date>1959-10-22</dcc:date> + <dcc:respAuthority> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + </dcc:location> + </dcc:respAuthority> + </dcc:statement> + </dcc:statements> + </dcc:administrativeData> + <dcc:measurementResults> + <dcc:measurementResult> + <dcc:name> + <dcc:content lang="de">Messergebnisse</dcc:content> + <dcc:content lang="en">Measurement results</dcc:content> + </dcc:name> + <dcc:usedMethods> + <dcc:usedMethod refType="gp_temperatureSensor"> + <dcc:name> + <dcc:content lang="de">Kalibrierung von Temperaturmessfühlern</dcc:content> + <dcc:content lang="en">Calibration of temperature sensors</dcc:content> + </dcc:name> + </dcc:usedMethod> + </dcc:usedMethods> + <dcc:measuringEquipments> + <dcc:measuringEquipment refType="basic_normalUsed"> + <dcc:name> + <dcc:content lang="de">Pt 100 Widerstandsthermometer</dcc:content> + <dcc:content lang="en">Pt 100 thermometer</dcc:content> + </dcc:name> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>manufacturer</dcc:issuer> + <dcc:value>string-manufacturer-measuringEquipment-1</dcc:value> + </dcc:identification> + </dcc:identifications> + </dcc:measuringEquipment> + </dcc:measuringEquipments> + <dcc:influenceConditions> + <dcc:influenceCondition refType="basic_temperature"> + <dcc:name> + <dcc:content lang="de">Umgebungsbedingung Temperatur</dcc:content> + <dcc:content lang="en">Ambient condition temperature</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Diese Werte wurden nicht gemessen, sondern wurden anhand der typischen Wetterbedingungen zu einer Jahreszeit angegeben. [^1]</dcc:content> + <dcc:content lang="en">These values were not measured, but were given based on typical weather conditions at a time of year. [^1]</dcc:content> + </dcc:description> + <dcc:data> + <dcc:quantity refType="basic_temperatureMin"> + <dcc:name> + <dcc:content lang="de">Temperatur min</dcc:content> + <dcc:content lang="en">temperature min</dcc:content> + </dcc:name> + <si:real> + <si:value>293</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + <dcc:quantity refType="basic_temperatureMax"> + <dcc:name> + <dcc:content lang="de">Temperatur max</dcc:content> + <dcc:content lang="en">temperature max</dcc:content> + </dcc:name> + <si:real> + <si:value>299</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:influenceCondition> + <dcc:influenceCondition refType="basic_humidityRelative"> + <dcc:name> + <dcc:content lang="de">Umgebungsbedingung relative Luftfeuchte</dcc:content> + <dcc:content lang="en">Ambient condition relative humidity</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Diese Werte wurden nicht gemessen, sondern wurden anhand der typischen Wetterbedingungen zu einer Jahreszeit angegeben. [^1]</dcc:content> + <dcc:content lang="en">These values were not measured, but were given based on typical weather conditions at a time of year. [^1]</dcc:content> + </dcc:description> + <dcc:data> + <dcc:quantity refType="basic_humidityRelativeMin"> + <dcc:name> + <dcc:content lang="de">Feuchte min</dcc:content> + <dcc:content lang="en">humidity min</dcc:content> + </dcc:name> + <si:real> + <si:value>0.20</si:value> + <si:unit>\one</si:unit> + </si:real> + </dcc:quantity> + <dcc:quantity refType="basic_humidityRelativeMax"> + <dcc:name> + <dcc:content lang="de">Feuchte max</dcc:content> + <dcc:content lang="en">humidity max</dcc:content> + </dcc:name> + <si:real> + <si:value>0.70</si:value> + <si:unit>\one</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:influenceCondition> + </dcc:influenceConditions> + <dcc:results> + <dcc:result refType="gp_measuringResult1"> + <dcc:name> + <dcc:content lang="de">Messergebnisse</dcc:content> + <dcc:content lang="en">Measuring results</dcc:content> + </dcc:name> + <dcc:data> + <dcc:list refType="gp_table1"> + <dcc:quantity refType="basic_referenceValue"> + <dcc:name> + <dcc:content lang="de">Bezugswert</dcc:content> + <dcc:content lang="en">Reference value</dcc:content> + </dcc:name> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306.248 373.121 448.253 523.319 593.154</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>33.098 99.971 175.103 250.169 320.004</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + <dcc:quantity refType="basic_measuredValue"> + <dcc:name> + <dcc:content lang="de">Angezeigter Messwert Kalibriergegenstand</dcc:content> + <dcc:content lang="en">Indicated measured value probe</dcc:content> + </dcc:name> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306.32 373.21 448.36 523.31 593.07</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>33.17 100.06 175.21 250.16 319.92</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + <dcc:quantity refType="basic_measurementError"> + <dcc:name> + <dcc:content lang="de">Messabweichung</dcc:content> + <dcc:content lang="en">Measurement error</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>0.072 0.089 0.107 -0.009 -0.084</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + <si:expandedUncXMLList> + <si:uncertaintyXMLList>0.061</si:uncertaintyXMLList> + <si:coverageFactorXMLList>2</si:coverageFactorXMLList> + <si:coverageProbabilityXMLList>0.95</si:coverageProbabilityXMLList> + <si:distributionXMLList>normal</si:distributionXMLList> + </si:expandedUncXMLList> + </si:realListXMLList> + <dcc:measurementMetaData> + <dcc:metaData refType="basic_conformity"> + <dcc:declaration> + <dcc:name> + <dcc:content lang="de">Konformität</dcc:content> + <dcc:content lang="en">Conformity</dcc:content> + </dcc:name> + </dcc:declaration> + <dcc:conformityXMLList>pass</dcc:conformityXMLList> + <dcc:data> + <dcc:quantity refType="basic_acceptanceLimitLower"> + <dcc:name> + <dcc:content lang="de">Unteres Akzeptanzlimit</dcc:content> + <dcc:content lang="en">Lower acceptance limit</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>-0.23 -0.23 -0.23 -0.30 -0.30</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + </dcc:quantity> + <dcc:quantity refType="basic_acceptanceLimitUpper"> + <dcc:name> + <dcc:content lang="de">Oberes Akzeptanzlimit</dcc:content> + <dcc:content lang="en">Upper acceptance limit</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>0.23 0.23 0.23 0.30 0.30</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + </dcc:quantity> + </dcc:data> + </dcc:metaData> + </dcc:measurementMetaData> + </dcc:quantity> + </dcc:list> + </dcc:data> + </dcc:result> + </dcc:results> + </dcc:measurementResult> + </dcc:measurementResults> +</dcc:digitalCalibrationCertificate> \ No newline at end of file diff --git a/tests/resources/GP_Temperature_Simplified_variant.xml b/tests/resources/GP_Temperature_Simplified_variant.xml new file mode 100644 index 0000000..6001e42 --- /dev/null +++ b/tests/resources/GP_Temperature_Simplified_variant.xml @@ -0,0 +1,365 @@ +<?xml version="1.0" encoding="utf-8"?> +<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dcc="https://ptb.de/dcc" xmlns:si="https://ptb.de/si" xsi:schemaLocation="https://ptb.de/dcc https://ptb.de/dcc/v3.2.0/dcc.xsd" schemaVersion="3.2.0"> + <dcc:administrativeData> + <dcc:dccSoftware> + <dcc:software> + <dcc:name> + <dcc:content>Notepad++ (32-bit)</dcc:content> + </dcc:name> + <dcc:release>v 8.2</dcc:release> + </dcc:software> + </dcc:dccSoftware> + <dcc:coreData> + <dcc:countryCodeISO3166_1>DE</dcc:countryCodeISO3166_1> + <dcc:usedLangCodeISO639_1>en</dcc:usedLangCodeISO639_1> + <dcc:usedLangCodeISO639_1>de</dcc:usedLangCodeISO639_1> + <dcc:mandatoryLangCodeISO639_1>en</dcc:mandatoryLangCodeISO639_1> + <dcc:uniqueIdentifier>GP_DCC_temperature_minimal_1.2</dcc:uniqueIdentifier> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>calibrationLaboratory</dcc:issuer> + <dcc:value>string-calibrationLaboratory-coreData</dcc:value> + <dcc:name> + <dcc:content lang="de">Auftrags Nr.</dcc:content> + <dcc:content lang="en">Order no.</dcc:content> + </dcc:name> + </dcc:identification> + </dcc:identifications> + <dcc:beginPerformanceDate>1957-08-13</dcc:beginPerformanceDate> + <dcc:endPerformanceDate>1957-08-13</dcc:endPerformanceDate> + <dcc:performanceLocation>laboratory</dcc:performanceLocation> + </dcc:coreData> + <dcc:items> + <dcc:item> + <dcc:name> + <dcc:content lang="de">Temperatur-Fühler</dcc:content> + <dcc:content lang="en">Temperature sensor</dcc:content> + </dcc:name> + <dcc:equipmentClass> + <dcc:reference>1.2.3.4.5</dcc:reference> + <dcc:classID>12345</dcc:classID> + </dcc:equipmentClass> + <dcc:manufacturer> + <dcc:name> + <dcc:content>String</dcc:content> + </dcc:name> + </dcc:manufacturer> + <dcc:model>String</dcc:model> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>manufacturer</dcc:issuer> + <dcc:value>string-manufacturer-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Serien Nr.</dcc:content> + <dcc:content lang="en">Serial no.</dcc:content> + </dcc:name> + </dcc:identification> + <dcc:identification> + <dcc:issuer>customer</dcc:issuer> + <dcc:value>string-customer-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Messmittel Nr.</dcc:content> + <dcc:content lang="en">Measurement equipment no.</dcc:content> + </dcc:name> + </dcc:identification> + <dcc:identification> + <dcc:issuer>calibrationLaboratory</dcc:issuer> + <dcc:value>string-calibrationLaboratory-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Equipment Nr.</dcc:content> + <dcc:content lang="en">Equipment no.</dcc:content> + </dcc:name> + </dcc:identification> + </dcc:identifications> + </dcc:item> + </dcc:items> + <dcc:calibrationLaboratory> + <dcc:contact> + <dcc:name> + <dcc:content>Kalibrierfirma GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kalibrierfirma.xx</dcc:eMail> + <dcc:phone>+49 123 4567-89</dcc:phone> + <dcc:fax>+49 123 4567-90</dcc:fax> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + <dcc:street>Musterstraße</dcc:street> + <dcc:streetNo>1</dcc:streetNo> + <dcc:further> + <dcc:content>www.kalibrierfirma.xx</dcc:content> + </dcc:further> + </dcc:location> + </dcc:contact> + </dcc:calibrationLaboratory> + <dcc:respPersons> + <dcc:respPerson> + <dcc:person> + <dcc:name> + <dcc:content>Michaela Musterfrau</dcc:content> + </dcc:name> + </dcc:person> + <dcc:mainSigner>true</dcc:mainSigner> + </dcc:respPerson> + <dcc:respPerson> + <dcc:person> + <dcc:name> + <dcc:content>Michael Mustermann</dcc:content> + </dcc:name> + </dcc:person> + </dcc:respPerson> + </dcc:respPersons> + <dcc:customer> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + <dcc:further> + <dcc:content lang="de">Kunden Nr. 1024418</dcc:content> + <dcc:content lang="en">Customer ID no. 1024418</dcc:content> + </dcc:further> + </dcc:location> + </dcc:customer> + <dcc:statements> + <dcc:statement refType="basic_conformity"> + <dcc:declaration> + <dcc:content lang="de">Die Konformitätsaussage erfolgt anhand der Vorgaben des Kunden. Sie sind im DCC mit aufgeführt.</dcc:content> + <dcc:content lang="en">The conformity statement is made on the basis of the customer's specifications. They are listed in the DCC.</dcc:content> + </dcc:declaration> + <dcc:respAuthority> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + </dcc:location> + </dcc:respAuthority> + <dcc:conformity>pass</dcc:conformity> + </dcc:statement> + <dcc:statement refType="basic_recalibration"> + <dcc:declaration> + <dcc:content lang="de">Datum, wann nach der Festlegung durch den Kunden spätestens der Kalibriergegenstand rekalibriert werden soll:</dcc:content> + <dcc:content lang="en">Date when the calibration item is to be recalibrated at the latest according to the customer's specification:</dcc:content> + </dcc:declaration> + <dcc:date>1959-10-22</dcc:date> + <dcc:respAuthority> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + </dcc:location> + </dcc:respAuthority> + </dcc:statement> + <dcc:statement> + <dcc:countryCodeISO3166_1>DE</dcc:countryCodeISO3166_1> + <dcc:countryCodeISO3166_1>US</dcc:countryCodeISO3166_1> + <dcc:convention>abcde</dcc:convention> + <dcc:traceable>true</dcc:traceable> + <dcc:period>P1Y2M3DT10H30M</dcc:period> + <dcc:nonSIDefinition>abcde_definition</dcc:nonSIDefinition> + <dcc:nonSIUnit>abcde_unit</dcc:nonSIUnit> + </dcc:statement> + </dcc:statements> + </dcc:administrativeData> + <dcc:measurementResults> + <dcc:measurementResult> + <dcc:name> + <dcc:content lang="de">Messergebnisse</dcc:content> + <dcc:content lang="en">Measurement results</dcc:content> + </dcc:name> + <dcc:usedMethods> + <dcc:usedMethod refType="gp_temperatureSensor"> + <dcc:name> + <dcc:content lang="de">Kalibrierung von Temperaturmessfühlern</dcc:content> + <dcc:content lang="en">Calibration of temperature sensors</dcc:content> + </dcc:name> + </dcc:usedMethod> + </dcc:usedMethods> + <dcc:measuringEquipments> + <dcc:measuringEquipment refType="basic_normalUsed"> + <dcc:name> + <dcc:content lang="de">Pt 100 Widerstandsthermometer</dcc:content> + <dcc:content lang="en">Pt 100 thermometer</dcc:content> + </dcc:name> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>manufacturer</dcc:issuer> + <dcc:value>string-manufacturer-measuringEquipment-1</dcc:value> + </dcc:identification> + </dcc:identifications> + </dcc:measuringEquipment> + </dcc:measuringEquipments> + <dcc:influenceConditions> + <dcc:influenceCondition refType="basic_temperature"> + <dcc:name> + <dcc:content lang="de">Umgebungsbedingung Temperatur</dcc:content> + <dcc:content lang="en">Ambient condition temperature</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Diese Werte wurden nicht gemessen, sondern wurden anhand der typischen Wetterbedingungen zu einer Jahreszeit angegeben. [^1]</dcc:content> + <dcc:content lang="en">These values were not measured, but were given based on typical weather conditions at a time of year. [^1]</dcc:content> + </dcc:description> + <dcc:data> + <dcc:quantity refType="basic_temperatureMin"> + <dcc:name> + <dcc:content lang="de">Temperatur min</dcc:content> + <dcc:content lang="en">temperature min</dcc:content> + </dcc:name> + <si:real> + <si:value>293</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + <dcc:quantity refType="basic_temperatureMax"> + <dcc:name> + <dcc:content lang="de">Temperatur max</dcc:content> + <dcc:content lang="en">temperature max</dcc:content> + </dcc:name> + <si:real> + <si:value>299</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:influenceCondition> + <dcc:influenceCondition refType="basic_humidityRelative"> + <dcc:name> + <dcc:content lang="de">Umgebungsbedingung relative Luftfeuchte</dcc:content> + <dcc:content lang="en">Ambient condition relative humidity</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Diese Werte wurden nicht gemessen, sondern wurden anhand der typischen Wetterbedingungen zu einer Jahreszeit angegeben. [^1]</dcc:content> + <dcc:content lang="en">These values were not measured, but were given based on typical weather conditions at a time of year. [^1]</dcc:content> + </dcc:description> + <dcc:data> + <dcc:quantity refType="basic_humidityRelativeMin"> + <dcc:name> + <dcc:content lang="de">Feuchte min</dcc:content> + <dcc:content lang="en">humidity min</dcc:content> + </dcc:name> + <si:real> + <si:value>0.20</si:value> + <si:unit>\one</si:unit> + </si:real> + </dcc:quantity> + <dcc:quantity refType="basic_humidityRelativeMax"> + <dcc:name> + <dcc:content lang="de">Feuchte max</dcc:content> + <dcc:content lang="en">humidity max</dcc:content> + </dcc:name> + <si:real> + <si:value>0.70</si:value> + <si:unit>\one</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:influenceCondition> + </dcc:influenceConditions> + <dcc:results> + <dcc:result refType="gp_measuringResult1"> + <dcc:name> + <dcc:content lang="de">Messergebnisse</dcc:content> + <dcc:content lang="en">Measuring results</dcc:content> + </dcc:name> + <dcc:data> + <dcc:list refType="gp_table1"> + <dcc:quantity refType="basic_referenceValue"> + <dcc:name> + <dcc:content lang="de">Bezugswert</dcc:content> + <dcc:content lang="en">Reference value</dcc:content> + </dcc:name> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306.248 373.121 448.253 523.319 593.154</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>33.098 99.971 175.103 250.169 320.004</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + <dcc:quantity refType="basic_measuredValue"> + <dcc:name> + <dcc:content lang="de">Angezeigter Messwert Kalibriergegenstand</dcc:content> + <dcc:content lang="en">Indicated measured value probe</dcc:content> + </dcc:name> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306.32 373.21 448.36 523.31 593.07</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>33.17 100.06 175.21 250.16 319.92</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + <dcc:quantity refType="basic_measurementError"> + <dcc:name> + <dcc:content lang="de">Messabweichung</dcc:content> + <dcc:content lang="en">Measurement error</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>0.072 0.089 0.107 -0.009 -0.084</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + <si:expandedUncXMLList> + <si:uncertaintyXMLList>0.061</si:uncertaintyXMLList> + <si:coverageFactorXMLList>2</si:coverageFactorXMLList> + <si:coverageProbabilityXMLList>0.95</si:coverageProbabilityXMLList> + <si:distributionXMLList>normal</si:distributionXMLList> + </si:expandedUncXMLList> + </si:realListXMLList> + <dcc:measurementMetaData> + <dcc:metaData refType="basic_conformity"> + <dcc:declaration> + <dcc:name> + <dcc:content lang="de">Konformität</dcc:content> + <dcc:content lang="en">Conformity</dcc:content> + </dcc:name> + </dcc:declaration> + <dcc:conformityXMLList>pass</dcc:conformityXMLList> + <dcc:data> + <dcc:quantity refType="basic_acceptanceLimitLower"> + <dcc:name> + <dcc:content lang="de">Unteres Akzeptanzlimit</dcc:content> + <dcc:content lang="en">Lower acceptance limit</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>-0.23 -0.23 -0.23 -0.30 -0.30</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + </dcc:quantity> + <dcc:quantity refType="basic_acceptanceLimitUpper"> + <dcc:name> + <dcc:content lang="de">Oberes Akzeptanzlimit</dcc:content> + <dcc:content lang="en">Upper acceptance limit</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>0.23 0.23 0.23 0.30 0.30</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + </dcc:quantity> + </dcc:data> + </dcc:metaData> + </dcc:measurementMetaData> + </dcc:quantity> + </dcc:list> + </dcc:data> + </dcc:result> + </dcc:results> + </dcc:measurementResult> + </dcc:measurementResults> +</dcc:digitalCalibrationCertificate> diff --git a/tests/resources/GP_Temperature_Typical.xml b/tests/resources/GP_Temperature_Typical.xml new file mode 100644 index 0000000..817bffb --- /dev/null +++ b/tests/resources/GP_Temperature_Typical.xml @@ -0,0 +1,441 @@ +<?xml version="1.0" encoding="utf-8"?> +<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dcc="https://ptb.de/dcc" xmlns:si="https://ptb.de/si" xsi:schemaLocation="https://ptb.de/dcc https://ptb.de/dcc/v3.2.0/dcc.xsd" schemaVersion="3.2.0"> + <dcc:administrativeData> + <dcc:dccSoftware> + <dcc:software> + <dcc:name> + <dcc:content>Notepad++ (32-bit)</dcc:content> + </dcc:name> + <dcc:release>v 8.2</dcc:release> + </dcc:software> + </dcc:dccSoftware> + <dcc:coreData> + <dcc:countryCodeISO3166_1>DE</dcc:countryCodeISO3166_1> + <dcc:usedLangCodeISO639_1>en</dcc:usedLangCodeISO639_1> + <dcc:usedLangCodeISO639_1>de</dcc:usedLangCodeISO639_1> + <dcc:mandatoryLangCodeISO639_1>en</dcc:mandatoryLangCodeISO639_1> + <dcc:uniqueIdentifier>GP_DCC_temperature_typical_1.2</dcc:uniqueIdentifier> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>calibrationLaboratory</dcc:issuer> + <dcc:value>string-calibrationLaboratory-coreData</dcc:value> + <dcc:name> + <dcc:content lang="de">Auftrags Nr.</dcc:content> + <dcc:content lang="en">Order no.</dcc:content> + </dcc:name> + </dcc:identification> + </dcc:identifications> + <dcc:receiptDate>1957-08-13</dcc:receiptDate> + <dcc:beginPerformanceDate>1957-08-13</dcc:beginPerformanceDate> + <dcc:endPerformanceDate>1957-08-13</dcc:endPerformanceDate> + <dcc:performanceLocation>laboratory</dcc:performanceLocation> + </dcc:coreData> + <dcc:items> + <dcc:item> + <dcc:name> + <dcc:content lang="de">Temperatur-Fühler</dcc:content> + <dcc:content lang="en">Temperature sensor</dcc:content> + </dcc:name> + <dcc:manufacturer> + <dcc:name> + <dcc:content>String</dcc:content> + </dcc:name> + </dcc:manufacturer> + <dcc:model>String</dcc:model> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>manufacturer</dcc:issuer> + <dcc:value>string-manufacturer-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Serien Nr.</dcc:content> + <dcc:content lang="en">Serial no.</dcc:content> + </dcc:name> + </dcc:identification> + <dcc:identification> + <dcc:issuer>customer</dcc:issuer> + <dcc:value>string-customer-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Messmittel Nr.</dcc:content> + <dcc:content lang="en">Measurement equipment no.</dcc:content> + </dcc:name> + </dcc:identification> + <dcc:identification> + <dcc:issuer>calibrationLaboratory</dcc:issuer> + <dcc:value>string-calibrationLaboratory-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Equipment Nr.</dcc:content> + <dcc:content lang="en">Equipment no.</dcc:content> + </dcc:name> + </dcc:identification> + </dcc:identifications> + </dcc:item> + </dcc:items> + <dcc:calibrationLaboratory> + <dcc:contact> + <dcc:name> + <dcc:content>Kalibrierfirma GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kalibrierfirma.xx</dcc:eMail> + <dcc:phone>+49 123 4567-89</dcc:phone> + <dcc:fax>+49 123 4567-90</dcc:fax> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + <dcc:street>Musterstraße</dcc:street> + <dcc:streetNo>1</dcc:streetNo> + <dcc:further> + <dcc:content>www.kalibrierfirma.xx</dcc:content> + </dcc:further> + </dcc:location> + </dcc:contact> + </dcc:calibrationLaboratory> + <dcc:respPersons> + <dcc:respPerson> + <dcc:person> + <dcc:name> + <dcc:content>Michaela Musterfrau</dcc:content> + </dcc:name> + </dcc:person> + <dcc:mainSigner>true</dcc:mainSigner> + </dcc:respPerson> + <dcc:respPerson> + <dcc:person> + <dcc:name> + <dcc:content>Michael Mustermann</dcc:content> + </dcc:name> + </dcc:person> + </dcc:respPerson> + </dcc:respPersons> + <dcc:customer> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + <dcc:further> + <dcc:content lang="de">Kunden Nr. 1024418</dcc:content> + <dcc:content lang="en">Customer ID no. 1024418</dcc:content> + </dcc:further> + </dcc:location> + </dcc:customer> + <dcc:statements> + <dcc:statement> + <dcc:norm>ISO/IEC 17025:2018-03</dcc:norm> + <dcc:reference>7.8.4.3</dcc:reference> + <dcc:declaration> + <dcc:content lang="de">Die Ergebnisse gelten zum Zeitpunkt der Kalibrierung. Es obliegt dem Antragsteller, zu gegebener Zeit eine Rekalibrierung zu veranlassen.</dcc:content> + <dcc:content lang="en">The results refer only to the object calibrated in this DCC. The measurement results are valid at the time of calibration. The applicant is responsible for arranging a recalibration in due time.</dcc:content> + </dcc:declaration> + </dcc:statement> + <dcc:statement refType="basic_validityRange"> + <dcc:declaration> + <dcc:content lang="de">Angabe des Temperaturbereichs, in dem kalibriert wurde:</dcc:content> + <dcc:content lang="en">Specification of the temperature range in which calibration was performed:</dcc:content> + </dcc:declaration> + <dcc:data> + <dcc:quantity refType="basic_validityRangeMin"> + <dcc:name> + <dcc:content lang="de">Unteres Limit</dcc:content> + <dcc:content lang="en">Lower limit</dcc:content> + </dcc:name> + <si:real> + <si:value>306</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + <dcc:quantity refType="basic_validityRangeMax"> + <dcc:name> + <dcc:content lang="de">Oberes Limit</dcc:content> + <dcc:content lang="en">Upper limit</dcc:content> + </dcc:name> + <si:real> + <si:value>593</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:statement> + <dcc:statement refType="basic_conformity"> + <dcc:declaration> + <dcc:content lang="de">Die Konformitätsaussage erfolgt anhand der Vorgaben des Kunden. Sie sind im DCC mit aufgeführt.</dcc:content> + <dcc:content lang="en">The conformity statement is made on the basis of the customer's specifications. They are listed in the DCC.</dcc:content> + </dcc:declaration> + <dcc:respAuthority> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + </dcc:location> + </dcc:respAuthority> + <dcc:conformity>pass</dcc:conformity> + </dcc:statement> + <dcc:statement refType="basic_recalibration"> + <dcc:declaration> + <dcc:content lang="de">Datum, wann nach der Festlegung durch den Kunden spätestens der Kalibriergegenstand rekalibriert werden soll:</dcc:content> + <dcc:content lang="en">Date when the calibration item is to be recalibrated at the latest according to the customer's specification:</dcc:content> + </dcc:declaration> + <dcc:date>1959-10-22</dcc:date> + <dcc:respAuthority> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + </dcc:location> + </dcc:respAuthority> + </dcc:statement> + </dcc:statements> + </dcc:administrativeData> + <dcc:measurementResults> + <dcc:measurementResult> + <dcc:name> + <dcc:content lang="de">Messergebnisse</dcc:content> + <dcc:content lang="en">Measurement results</dcc:content> + </dcc:name> + <dcc:usedMethods> + <dcc:usedMethod refType="basic_uncertainty"> + <dcc:name> + <dcc:content lang="de">Erweiterte Messunsicherheit</dcc:content> + <dcc:content lang="en">Expanded uncertainty</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Angegeben ist die erweiterte Messunsicherheit, die sich aus der Standardmessunsicherheit durch Multiplikation mit dem Erweiterungsfaktor k=2 ergibt. Sie wurde gemäß dem „Guide to the Expression of Uncertainty in Measurement (GUM)“ ermittelt. Der Wert der Messgröße liegt dann im Regelfall mit einer Wahrscheinlichkeit von annähernd 95 % im zugeordneten Überdeckungsintervall.</dcc:content> + <dcc:content lang="en">The expanded uncertainty was calculated from the contributions of uncertainty originating from the standards used, from the weighings and the air buoyancy corrections. The reported uncertainty does not include an estimate of long-term variations.</dcc:content> + </dcc:description> + <dcc:norm>GUM</dcc:norm> + </dcc:usedMethod> + <dcc:usedMethod refType="gp_temperatureSensor"> + <dcc:name> + <dcc:content lang="de">Kalibrierung von Temperaturmessfühlern</dcc:content> + <dcc:content lang="en">Calibration of temperature sensors</dcc:content> + </dcc:name> + <dcc:norm>DKD-R 5-1:2018</dcc:norm> + </dcc:usedMethod> + </dcc:usedMethods> + <dcc:measuringEquipments> + <dcc:measuringEquipment refType="basic_normalUsed"> + <dcc:name> + <dcc:content lang="de">Pt 100 Widerstandsthermometer</dcc:content> + <dcc:content lang="en">Pt 100 thermometer</dcc:content> + </dcc:name> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>manufacturer</dcc:issuer> + <dcc:value>string-manufacturer-measuringEquipment-1</dcc:value> + </dcc:identification> + </dcc:identifications> + </dcc:measuringEquipment> + </dcc:measuringEquipments> + <dcc:influenceConditions> + <dcc:influenceCondition refType="gp_immersionDepth"> + <dcc:name> + <dcc:content lang="de">Eintauchtiefe im Wasserbad</dcc:content> + <dcc:content lang="en">Immersion depth in water bath</dcc:content> + </dcc:name> + <dcc:data> + <dcc:quantity> + <dcc:name> + <dcc:content lang="de">Eintauchtiefe</dcc:content> + <dcc:content lang="en">Immersion depth</dcc:content> + </dcc:name> + <si:real> + <si:value>0.1</si:value> + <si:unit>\metre</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:influenceCondition> + <dcc:influenceCondition refType="basic_temperature"> + <dcc:name> + <dcc:content lang="de">Umgebungsbedingung Temperatur</dcc:content> + <dcc:content lang="en">Ambient condition temperature</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Diese Werte wurden nicht gemessen, sondern wurden anhand der typischen Wetterbedingungen zu einer Jahreszeit angegeben. [^1]</dcc:content> + <dcc:content lang="en">These values were not measured, but were given based on typical weather conditions at a time of year. [^1]</dcc:content> + </dcc:description> + <dcc:data> + <dcc:quantity refType="basic_temperatureMin"> + <dcc:name> + <dcc:content lang="de">Temperatur min</dcc:content> + <dcc:content lang="en">temperature min</dcc:content> + </dcc:name> + <si:real> + <si:value>293</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + <dcc:quantity refType="basic_temperatureMax"> + <dcc:name> + <dcc:content lang="de">Temperatur max</dcc:content> + <dcc:content lang="en">temperature max</dcc:content> + </dcc:name> + <si:real> + <si:value>299</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:influenceCondition> + <dcc:influenceCondition refType="basic_humidityRelative"> + <dcc:name> + <dcc:content lang="de">Umgebungsbedingung relative Luftfeuchte</dcc:content> + <dcc:content lang="en">Ambient condition relative humidity</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Diese Werte wurden nicht gemessen, sondern wurden anhand der typischen Wetterbedingungen zu einer Jahreszeit angegeben. [^1]</dcc:content> + <dcc:content lang="en">These values were not measured, but were given based on typical weather conditions at a time of year. [^1]</dcc:content> + </dcc:description> + <dcc:data> + <dcc:quantity refType="basic_humidityRelativeMin"> + <dcc:name> + <dcc:content lang="de">Feuchte min</dcc:content> + <dcc:content lang="en">humidity min</dcc:content> + </dcc:name> + <si:real> + <si:value>0.20</si:value> + <si:unit>\one</si:unit> + </si:real> + </dcc:quantity> + <dcc:quantity refType="basic_humidityRelativeMax"> + <dcc:name> + <dcc:content lang="de">Feuchte max</dcc:content> + <dcc:content lang="en">humidity max</dcc:content> + </dcc:name> + <si:real> + <si:value>0.70</si:value> + <si:unit>\one</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:influenceCondition> + </dcc:influenceConditions> + <dcc:results> + <dcc:result refType="gp_measuringResult1"> + <dcc:name> + <dcc:content lang="de">Messergebnisse</dcc:content> + <dcc:content lang="en">Measuring results</dcc:content> + </dcc:name> + <dcc:data> + <dcc:list refType="gp_table1"> + <dcc:quantity refType="basic_referenceValue"> + <dcc:name> + <dcc:content lang="de">Bezugswert</dcc:content> + <dcc:content lang="en">Reference value</dcc:content> + </dcc:name> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306.248 373.121 448.253 523.319 593.154</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>33.098 99.971 175.103 250.169 320.004</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + <dcc:measurementMetaData> + <dcc:metaData refType="basic_calibrationValue"> + <dcc:declaration> + <dcc:content lang="de">Kalibrierpunkt</dcc:content> + <dcc:content lang="en">Calibration value</dcc:content> + </dcc:declaration> + <dcc:data> + <dcc:quantity> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306 373 448 523 593</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>32.85 99.85 174.85 249.85 319.85</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + </dcc:data> + </dcc:metaData> + </dcc:measurementMetaData> + </dcc:quantity> + <dcc:quantity refType="basic_measuredValue"> + <dcc:name> + <dcc:content lang="de">Angezeigter Messwert Kalibriergegenstand</dcc:content> + <dcc:content lang="en">Indicated measured value probe</dcc:content> + </dcc:name> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306.32 373.21 448.36 523.31 593.07</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>33.17 100.06 175.21 250.16 319.92</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + <dcc:quantity refType="basic_measurementError"> + <dcc:name> + <dcc:content lang="de">Messabweichung</dcc:content> + <dcc:content lang="en">Measurement error</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>0.072 0.089 0.107 -0.009 -0.084</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + <si:expandedUncXMLList> + <si:uncertaintyXMLList>0.061</si:uncertaintyXMLList> + <si:coverageFactorXMLList>2</si:coverageFactorXMLList> + <si:coverageProbabilityXMLList>0.95</si:coverageProbabilityXMLList> + <si:distributionXMLList>normal</si:distributionXMLList> + </si:expandedUncXMLList> + </si:realListXMLList> + <dcc:measurementMetaData> + <dcc:metaData refType="basic_conformity"> + <dcc:declaration> + <dcc:name> + <dcc:content lang="de">Konformität</dcc:content> + <dcc:content lang="en">Conformity</dcc:content> + </dcc:name> + </dcc:declaration> + <dcc:conformityXMLList>pass</dcc:conformityXMLList> + <dcc:data> + <dcc:quantity refType="basic_acceptanceLimitLower"> + <dcc:name> + <dcc:content lang="de">Unteres Akzeptanzlimit</dcc:content> + <dcc:content lang="en">Lower acceptance limit</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>-0.23 -0.23 -0.23 -0.30 -0.30</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + </dcc:quantity> + <dcc:quantity refType="basic_acceptanceLimitUpper"> + <dcc:name> + <dcc:content lang="de">Oberes Akzeptanzlimit</dcc:content> + <dcc:content lang="en">Upper acceptance limit</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>0.23 0.23 0.23 0.30 0.30</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + </dcc:quantity> + </dcc:data> + </dcc:metaData> + </dcc:measurementMetaData> + </dcc:quantity> + </dcc:list> + </dcc:data> + </dcc:result> + </dcc:results> + </dcc:measurementResult> + </dcc:measurementResults> +</dcc:digitalCalibrationCertificate> \ No newline at end of file diff --git a/tests/resources/GP_Temperature_v3.2.0_DCC.xml b/tests/resources/GP_Temperature_v3.2.0_DCC.xml new file mode 100644 index 0000000..6cf833b --- /dev/null +++ b/tests/resources/GP_Temperature_v3.2.0_DCC.xml @@ -0,0 +1,540 @@ +<?xml version="1.0" encoding="UTF-8"?> +<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dcc="https://ptb.de/dcc" xmlns:si="https://ptb.de/si" xsi:schemaLocation="https://ptb.de/dcc https://ptb.de/dcc/v3.2.0/dcc.xsd" schemaVersion="3.2.0"> + <dcc:administrativeData> + <dcc:dccSoftware> + <dcc:software> + <dcc:name> + <dcc:content>Notepad++ (32-bit)</dcc:content> + </dcc:name> + <dcc:release>v 8.2</dcc:release> + <dcc:type>application</dcc:type> + <dcc:description> + <dcc:name> + <dcc:content>Open source text editor</dcc:content> + </dcc:name> + <dcc:content>https://notepad-plus-plus.org/downloads/</dcc:content> + </dcc:description> + </dcc:software> + </dcc:dccSoftware> + <dcc:refTypeDefinitions> + <dcc:refTypeDefinition> + <dcc:name> + <dcc:content>Cross-Community refType Definition</dcc:content> + </dcc:name> + <dcc:description> + <dcc:name> + <dcc:content>Description name ABC</dcc:content> + </dcc:name> + <dcc:content>Description ABC</dcc:content> + </dcc:description> + <dcc:namespace>basic</dcc:namespace> + <dcc:link>https://www.ptb.de/dcc/refType/basic/draft_basic.xml</dcc:link> + <dcc:release>0.1</dcc:release> + <dcc:value>Value ABC</dcc:value> + <dcc:procedure>Procedure ABC</dcc:procedure> + </dcc:refTypeDefinition> + </dcc:refTypeDefinitions> + <dcc:coreData> + <dcc:countryCodeISO3166_1>DE</dcc:countryCodeISO3166_1> + <dcc:usedLangCodeISO639_1>en</dcc:usedLangCodeISO639_1> + <dcc:usedLangCodeISO639_1>de</dcc:usedLangCodeISO639_1> + <dcc:mandatoryLangCodeISO639_1>en</dcc:mandatoryLangCodeISO639_1> + <dcc:uniqueIdentifier>GP_DCC_temperature_minimal_1.1_Complete</dcc:uniqueIdentifier> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>calibrationLaboratory</dcc:issuer> + <dcc:value>string-calibrationLaboratory-coreData</dcc:value> + <dcc:name> + <dcc:content lang="de">Auftrags Nr.</dcc:content> + <dcc:content lang="en">Order no.</dcc:content> + </dcc:name> + </dcc:identification> + </dcc:identifications> + <dcc:receiptDate>1957-08-13</dcc:receiptDate> + <dcc:beginPerformanceDate>1957-08-13</dcc:beginPerformanceDate> + <dcc:endPerformanceDate>1957-08-13</dcc:endPerformanceDate> + <dcc:performanceLocation>laboratory</dcc:performanceLocation> + <dcc:issueDate>2022-12-31</dcc:issueDate> + <!-- TODO: dcc:previousReport --> + </dcc:coreData> + <dcc:items> + <dcc:item refType="test_items"> + <dcc:name> + <dcc:content lang="de">Temperatur-Fühler</dcc:content> + <dcc:content lang="en">Temperature sensor</dcc:content> + </dcc:name> + <dcc:manufacturer> + <dcc:name> + <dcc:content>String</dcc:content> + </dcc:name> + </dcc:manufacturer> + <dcc:model>String</dcc:model> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>manufacturer</dcc:issuer> + <dcc:value>string-manufacturer-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Serien Nr.</dcc:content> + <dcc:content lang="en">Serial no.</dcc:content> + </dcc:name> + </dcc:identification> + <dcc:identification> + <dcc:issuer>customer</dcc:issuer> + <dcc:value>string-customer-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Messmittel Nr.</dcc:content> + <dcc:content lang="en">Measurement equipment no.</dcc:content> + </dcc:name> + </dcc:identification> + <dcc:identification> + <dcc:issuer>calibrationLaboratory</dcc:issuer> + <dcc:value>string-calibrationLaboratory-item</dcc:value> + <dcc:name> + <dcc:content lang="de">Equipment Nr.</dcc:content> + <dcc:content lang="en">Equipment no.</dcc:content> + </dcc:name> + </dcc:identification> + </dcc:identifications> + <dcc:itemQuantities> + <dcc:itemQuantity> + <dcc:name> + <dcc:content lang="de">Name der ItemQuantity</dcc:content> + <dcc:content lang="en">Name of the item quantity</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content>Membrandurchmesser</dcc:content> + </dcc:description> + <si:real> + <si:value>0.05</si:value> + <si:unit>\metre</si:unit> + </si:real> + </dcc:itemQuantity> + <dcc:itemQuantity> + <dcc:description> + <dcc:content>Membranstärke</dcc:content> + </dcc:description> + <si:real> + <si:value>0.0003</si:value> + <si:unit>\metre</si:unit> + </si:real> + </dcc:itemQuantity> + </dcc:itemQuantities> + </dcc:item> + </dcc:items> + <dcc:calibrationLaboratory> + <dcc:contact> + <dcc:name> + <dcc:content>Kalibrierfirma GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kalibrierfirma.xx</dcc:eMail> + <dcc:phone>+49 123 4567-89</dcc:phone> + <dcc:fax>+49 123 4567-90</dcc:fax> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + <dcc:street>Musterstraße</dcc:street> + <dcc:streetNo>1</dcc:streetNo> + <dcc:further> + <dcc:content>www.kalibrierfirma.xx</dcc:content> + </dcc:further> + </dcc:location> + </dcc:contact> + <dcc:cryptElectronicSeal>true</dcc:cryptElectronicSeal> + <dcc:cryptElectronicSignature>false</dcc:cryptElectronicSignature> + <dcc:cryptElectronicTimeStamp>true</dcc:cryptElectronicTimeStamp> + </dcc:calibrationLaboratory> + <dcc:respPersons> + <dcc:respPerson refType="test_respPerson"> + <dcc:person> + <dcc:name> + <dcc:content>Michaela Musterfrau</dcc:content> + </dcc:name> + </dcc:person> + <dcc:mainSigner>true</dcc:mainSigner> + </dcc:respPerson> + <dcc:respPerson> + <dcc:person> + <dcc:name> + <dcc:content>Michael Mustermann</dcc:content> + </dcc:name> + </dcc:person> + </dcc:respPerson> + </dcc:respPersons> + <dcc:customer> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + <dcc:further> + <dcc:content lang="de">Kunden Nr. 1024418</dcc:content> + <dcc:content lang="en">Customer ID no. 1024418</dcc:content> + </dcc:further> + </dcc:location> + </dcc:customer> + <dcc:statements> + <dcc:statement refType="basic_conformity"> + <dcc:name> + <dcc:content lang="de">Name der Konformitätsaussage</dcc:content> + <dcc:content lang="en">Name of conformity statement</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Beschreibung der Konformitätsaussage</dcc:content> + <dcc:content lang="en">Description of conformity statement</dcc:content> + </dcc:description> + <dcc:declaration> + <dcc:content lang="de">Die Konformitätsaussage erfolgt anhand der Vorgaben des Kunden. Sie sind im DCC mit aufgeführt.</dcc:content> + <dcc:content lang="en">The conformity statement is made on the basis of the customer's specifications. They are listed in the DCC.</dcc:content> + </dcc:declaration> + <dcc:respAuthority> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + </dcc:location> + </dcc:respAuthority> + <dcc:conformity>pass</dcc:conformity> + <dcc:data> + <dcc:quantity> + <dcc:name> + <dcc:content lang="de">Übertragungskoeffizient Phasenverschiebung</dcc:content> + <dcc:content lang="en">en</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>-0.02 -0.03 -0.02 -0.02 -0.01</si:valueXMLList> + <si:unitXMLList>\degree</si:unitXMLList> + <si:expandedUncXMLList> + <si:uncertaintyXMLList>0.3 0.3 0.3 0.3 0.3</si:uncertaintyXMLList> + <si:coverageFactorXMLList>2</si:coverageFactorXMLList> + <si:coverageProbabilityXMLList>0.95</si:coverageProbabilityXMLList> + <si:distributionXMLList>normal</si:distributionXMLList> + </si:expandedUncXMLList> + </si:realListXMLList> + <dcc:measurementMetaData> + <dcc:metaData> + <dcc:declaration> + <dcc:content lang="de">Kommentar ist gültig für den dritten Eintrag.</dcc:content> + </dcc:declaration> + <dcc:validXMLList>false false true false false</dcc:validXMLList> + </dcc:metaData> + </dcc:measurementMetaData> + </dcc:quantity> + </dcc:data> + </dcc:statement> + <dcc:statement refType="basic_recalibration"> + <dcc:declaration> + <dcc:content lang="de">Datum, wann nach der Festlegung durch den Kunden spätestens der Kalibriergegenstand rekalibriert werden soll:</dcc:content> + <dcc:content lang="en">Date when the calibration item is to be recalibrated at the latest according to the customer's specification:</dcc:content> + </dcc:declaration> + <dcc:date>1959-10-22</dcc:date> + <dcc:respAuthority> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:eMail>info@kunde.xx</dcc:eMail> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + <dcc:countryCode>DE</dcc:countryCode> + <dcc:postCode>00900</dcc:postCode> + </dcc:location> + </dcc:respAuthority> + </dcc:statement> + </dcc:statements> + </dcc:administrativeData> + <dcc:measurementResults> + <dcc:measurementResult> + <dcc:name> + <dcc:content lang="de">Messergebnisse</dcc:content> + <dcc:content lang="en">Measurement results</dcc:content> + </dcc:name> + <dcc:usedMethods> + <dcc:usedMethod refType="gp_temperatureSensor"> + <dcc:name> + <dcc:content lang="de">Kalibrierung von Temperaturmessfühlern</dcc:content> + <dcc:content lang="en">Calibration of temperature sensors</dcc:content> + </dcc:name> + </dcc:usedMethod> + </dcc:usedMethods> + <dcc:measuringEquipments> + <dcc:measuringEquipment refType="basic_normalUsed"> + <dcc:name> + <dcc:content lang="de">Pt 100 Widerstandsthermometer</dcc:content> + <dcc:content lang="en">Pt 100 thermometer</dcc:content> + </dcc:name> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>manufacturer</dcc:issuer> + <dcc:value>string-manufacturer-measuringEquipment-1</dcc:value> + </dcc:identification> + </dcc:identifications> + </dcc:measuringEquipment> + </dcc:measuringEquipments> + <dcc:influenceConditions> + <dcc:influenceCondition refType="basic_temperature"> + <dcc:name> + <dcc:content lang="de">Umgebungsbedingung Temperatur</dcc:content> + <dcc:content lang="en">Ambient condition temperature</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Diese Werte wurden nicht gemessen, sondern wurden anhand der typischen Wetterbedingungen zu einer Jahreszeit angegeben. [^1]</dcc:content> + <dcc:content lang="en">These values were not measured, but were given based on typical weather conditions at a time of year. [^1]</dcc:content> + </dcc:description> + <dcc:data> + <dcc:quantity refType="basic_temperatureMin"> + <dcc:name> + <dcc:content lang="de">Temperatur min</dcc:content> + <dcc:content lang="en">temperature min</dcc:content> + </dcc:name> + <si:real> + <si:value>293</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + <dcc:quantity refType="basic_temperatureMax"> + <dcc:name> + <dcc:content lang="de">Temperatur max</dcc:content> + <dcc:content lang="en">temperature max</dcc:content> + </dcc:name> + <si:real> + <si:value>299</si:value> + <si:unit>\kelvin</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:influenceCondition> + <dcc:influenceCondition refType="basic_humidityRelative"> + <dcc:name> + <dcc:content lang="de">Umgebungsbedingung relative Luftfeuchte</dcc:content> + <dcc:content lang="en">Ambient condition relative humidity</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Diese Werte wurden nicht gemessen, sondern wurden anhand der typischen Wetterbedingungen zu einer Jahreszeit angegeben. [^1]</dcc:content> + <dcc:content lang="en">These values were not measured, but were given based on typical weather conditions at a time of year. [^1]</dcc:content> + </dcc:description> + <dcc:data> + <dcc:quantity refType="basic_humidityRelativeMin"> + <dcc:name> + <dcc:content lang="de">Feuchte min</dcc:content> + <dcc:content lang="en">humidity min</dcc:content> + </dcc:name> + <si:real> + <si:value>0.20</si:value> + <si:unit>\one</si:unit> + </si:real> + </dcc:quantity> + <dcc:quantity refType="basic_humidityRelativeMax"> + <dcc:name> + <dcc:content lang="de">Feuchte max</dcc:content> + <dcc:content lang="en">humidity max</dcc:content> + </dcc:name> + <si:real> + <si:value>0.70</si:value> + <si:unit>\one</si:unit> + </si:real> + </dcc:quantity> + </dcc:data> + </dcc:influenceCondition> + </dcc:influenceConditions> + <dcc:results> + <dcc:result refType="gp_measuringResult1"> + <dcc:name> + <dcc:content lang="de">Messergebnisse</dcc:content> + <dcc:content lang="en">Measuring results</dcc:content> + </dcc:name> + <dcc:data> + <dcc:list refType="gp_table1"> + <dcc:quantity refType="basic_referenceValue"> + <dcc:name> + <dcc:content lang="de">Bezugswert</dcc:content> + <dcc:content lang="en">Reference value</dcc:content> + </dcc:name> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306.248 373.121 448.253 523.319 593.154</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>33.098 99.971 175.103 250.169 320.004</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + <dcc:quantity refType="basic_measuredValue"> + <dcc:name> + <dcc:content lang="de">Angezeigter Messwert Kalibriergegenstand</dcc:content> + <dcc:content lang="en">Indicated measured value probe</dcc:content> + </dcc:name> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306.32 373.21 448.36 523.31 593.07</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>33.17 100.06 175.21 250.16 319.92</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + <dcc:quantity refType="basic_measurementError"> + <dcc:name> + <dcc:content lang="de">Messabweichung</dcc:content> + <dcc:content lang="en">Measurement error</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>0.072 0.089 0.107 -0.009 -0.084</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + <si:expandedUncXMLList> + <si:uncertaintyXMLList>0.061</si:uncertaintyXMLList> + <si:coverageFactorXMLList>2</si:coverageFactorXMLList> + <si:coverageProbabilityXMLList>0.95</si:coverageProbabilityXMLList> + <si:distributionXMLList>normal</si:distributionXMLList> + </si:expandedUncXMLList> + </si:realListXMLList> + <dcc:measurementMetaData> + <dcc:metaData refType="basic_conformity"> + <dcc:name> + <dcc:content lang="de">Metadaten 1</dcc:content> + <dcc:content lang="en">Meta data 1</dcc:content> + </dcc:name> + <dcc:description> + <dcc:content lang="de">Beschreibung der Metadaten 1</dcc:content> + <dcc:content lang="en">Description of Meta data 1</dcc:content> + </dcc:description> + <dcc:declaration> + <dcc:name> + <dcc:content lang="de">Konformität</dcc:content> + <dcc:content lang="en">Conformity</dcc:content> + </dcc:name> + </dcc:declaration> + <dcc:conformityXMLList>pass</dcc:conformityXMLList> + <dcc:data> + <dcc:quantity refType="basic_acceptanceLimitLower"> + <dcc:name> + <dcc:content lang="de">Unteres Akzeptanzlimit</dcc:content> + <dcc:content lang="en">Lower acceptance limit</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>-0.23 -0.23 -0.23 -0.30 -0.30</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + </dcc:quantity> + <dcc:quantity refType="basic_acceptanceLimitUpper"> + <dcc:name> + <dcc:content lang="de">Oberes Akzeptanzlimit</dcc:content> + <dcc:content lang="en">Upper acceptance limit</dcc:content> + </dcc:name> + <si:realListXMLList> + <si:valueXMLList>0.23 0.23 0.23 0.30 0.30</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + </dcc:quantity> + </dcc:data> + </dcc:metaData> + </dcc:measurementMetaData> + </dcc:quantity> + </dcc:list> + <dcc:quantity refType="test_noQuantity"> + <dcc:noQuantity> + <dcc:name> + <dcc:content>Example name</dcc:content> + </dcc:name> + <dcc:content>Example text</dcc:content> + <dcc:file refType="examplePicture"> + <dcc:fileName>examplePicture.png</dcc:fileName> + <dcc:mimeType>image/png</dcc:mimeType> + <dcc:dataBase64>iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAEDmlDQ1BrQ0dDb2xvclNwYWNlR2VuZXJpY1JHQgAAOI2NVV1oHFUUPpu5syskzoPUpqaSDv41lLRsUtGE2uj+ZbNt3CyTbLRBkMns3Z1pJjPj/KRpKT4UQRDBqOCT4P9bwSchaqvtiy2itFCiBIMo+ND6R6HSFwnruTOzu5O4a73L3PnmnO9+595z7t4LkLgsW5beJQIsGq4t5dPis8fmxMQ6dMF90A190C0rjpUqlSYBG+PCv9rt7yDG3tf2t/f/Z+uuUEcBiN2F2Kw4yiLiZQD+FcWyXYAEQfvICddi+AnEO2ycIOISw7UAVxieD/Cyz5mRMohfRSwoqoz+xNuIB+cj9loEB3Pw2448NaitKSLLRck2q5pOI9O9g/t/tkXda8Tbg0+PszB9FN8DuPaXKnKW4YcQn1Xk3HSIry5ps8UQ/2W5aQnxIwBdu7yFcgrxPsRjVXu8HOh0qao30cArp9SZZxDfg3h1wTzKxu5E/LUxX5wKdX5SnAzmDx4A4OIqLbB69yMesE1pKojLjVdoNsfyiPi45hZmAn3uLWdpOtfQOaVmikEs7ovj8hFWpz7EV6mel0L9Xy23FMYlPYZenAx0yDB1/PX6dledmQjikjkXCxqMJS9WtfFCyH9XtSekEF+2dH+P4tzITduTygGfv58a5VCTH5PtXD7EFZiNyUDBhHnsFTBgE0SQIA9pfFtgo6cKGuhooeilaKH41eDs38Ip+f4At1Rq/sjr6NEwQqb/I/DQqsLvaFUjvAx+eWirddAJZnAj1DFJL0mSg/gcIpPkMBkhoyCSJ8lTZIxk0TpKDjXHliJzZPO50dR5ASNSnzeLvIvod0HG/mdkmOC0z8VKnzcQ2M/Yz2vKldduXjp9bleLu0ZWn7vWc+l0JGcaai10yNrUnXLP/8Jf59ewX+c3Wgz+B34Df+vbVrc16zTMVgp9um9bxEfzPU5kPqUtVWxhs6OiWTVW+gIfywB9uXi7CGcGW/zk98k/kmvJ95IfJn/j3uQ+4c5zn3Kfcd+AyF3gLnJfcl9xH3OfR2rUee80a+6vo7EK5mmXUdyfQlrYLTwoZIU9wsPCZEtP6BWGhAlhL3p2N6sTjRdduwbHsG9kq32sgBepc+xurLPW4T9URpYGJ3ym4+8zA05u44QjST8ZIoVtu3qE7fWmdn5LPdqvgcZz8Ww8BWJ8X3w0PhQ/wnCDGd+LvlHs8dRy6bLLDuKMaZ20tZrqisPJ5ONiCq8yKhYM5cCgKOu66Lsc0aYOtZdo5QCwezI4wm9J/v0X23mlZXOfBjj8Jzv3WrY5D+CsA9D7aMs2gGfjve8ArD6mePZSeCfEYt8CONWDw8FXTxrPqx/r9Vt4biXeANh8vV7/+/16ffMD1N8AuKD/A/8leAvFY9bLAAAAOGVYSWZNTQAqAAAACAABh2kABAAAAAEAAAAaAAAAAAACoAIABAAAAAEAAAAUoAMABAAAAAEAAAAUAAAAAJEV0scAAAAtSURBVDgRY2RgYPgPxFQDTFQzCWrQqIGUh+hoGI6GIRkhMJpsyAg0NC0jMAwBzu4BJ2FWhpgAAAAASUVORK5CYII=</dcc:dataBase64> + </dcc:file> + <dcc:formula> + <dcc:latex>E = mc^2</dcc:latex> + </dcc:formula> + </dcc:noQuantity> + </dcc:quantity> + <dcc:quantity refType="test_charsXMLList"> + <dcc:charsXMLList>A B C D E F</dcc:charsXMLList> + </dcc:quantity> + <dcc:quantity refType="test_constant"> + <si:constant> + <si:label>exampleLabel</si:label> + <si:value>306.248</si:value> + <si:unit>\kelvin</si:unit> + <si:dateTime>1111-11-11T11:11:11</si:dateTime> + </si:constant> + </dcc:quantity> + <dcc:quantity refType="test_real"> + <si:real> + <si:label>exampleLabel</si:label> + <si:value>306.248</si:value> + <si:unit>\kelvin</si:unit> + <si:dateTime>1111-11-11T11:11:11</si:dateTime> + </si:real> + </dcc:quantity> + <dcc:quantity refType="test_realListXMLList"> + <si:realListXMLList> + <si:labelXMLList>exampleLabel</si:labelXMLList> + <si:valueXMLList>306.248 373.121 448.253 523.319 593.154</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + <si:dateTimeXMLList>1111-11-11T11:11:11 1111-11-11T11:11:12 1111-11-11T11:11:13 1111-11-11T11:11:14 1111-11-11T11:11:15</si:dateTimeXMLList> + </si:realListXMLList> + </dcc:quantity> + <dcc:quantity refType="test_hybridConstant"> + <si:hybrid> + <si:constant> + <si:label>exampleLabel</si:label> + <si:value>306.248</si:value> + <si:unit>\kelvin</si:unit> + <si:dateTime>1111-11-11T11:11:11</si:dateTime> + </si:constant> + <si:constant> + <si:label>exampleLabel</si:label> + <si:value>33.098</si:value> + <si:unit>\degreecelsius</si:unit> + <si:dateTime>1111-11-11T11:11:11</si:dateTime> + </si:constant> + </si:hybrid> + </dcc:quantity> + <dcc:quantity refType="test_hybridReal"> + <si:hybrid> + <si:real> + <si:label>exampleLabel</si:label> + <si:value>306.248</si:value> + <si:unit>\kelvin</si:unit> + <si:dateTime>1111-11-11T11:11:11</si:dateTime> + </si:real> + <si:real> + <si:label>exampleLabel</si:label> + <si:value>33.098</si:value> + <si:unit>\degreecelsius</si:unit> + <si:dateTime>1111-11-11T11:11:11</si:dateTime> + </si:real> + </si:hybrid> + </dcc:quantity> + <dcc:quantity refType="test_hybridRealListXMLList"> + <si:hybrid> + <si:realListXMLList> + <si:labelXMLList>exampleLabel</si:labelXMLList> + <si:valueXMLList>306.248 373.121 448.253 523.319 593.154</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + <si:dateTimeXMLList>1111-11-11T11:11:11 1111-11-11T11:11:12 1111-11-11T11:11:13 1111-11-11T11:11:14 1111-11-11T11:11:15</si:dateTimeXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:labelXMLList>exampleLabel</si:labelXMLList> + <si:valueXMLList>33.098 99.971 175.103 250.169 320.004</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + <si:dateTimeXMLList>1111-11-11T11:11:11 1111-11-11T11:11:12 1111-11-11T11:11:13 1111-11-11T11:11:14 1111-11-11T11:11:15</si:dateTimeXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + </dcc:data> + </dcc:result> + </dcc:results> + </dcc:measurementResult> + </dcc:measurementResults> +</dcc:digitalCalibrationCertificate> \ No newline at end of file diff --git a/tests/resources/Test_DCC_Minimal.xml b/tests/resources/Test_DCC_Minimal.xml new file mode 100644 index 0000000..7707aa1 --- /dev/null +++ b/tests/resources/Test_DCC_Minimal.xml @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="utf-8"?> +<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dcc="https://ptb.de/dcc" xmlns:si="https://ptb.de/si" xsi:schemaLocation="https://ptb.de/dcc https://ptb.de/dcc/v3.2.0/dcc.xsd" schemaVersion="3.2.0"> + <dcc:administrativeData> + <dcc:dccSoftware> + <dcc:software> + <dcc:name> + <dcc:content>Notepad++ (32-bit)</dcc:content> + </dcc:name> + <dcc:release>v 8.2</dcc:release> + </dcc:software> + </dcc:dccSoftware> + <dcc:coreData> + <dcc:countryCodeISO3166_1>DE</dcc:countryCodeISO3166_1> + <dcc:usedLangCodeISO639_1>en</dcc:usedLangCodeISO639_1> + <dcc:mandatoryLangCodeISO639_1>en</dcc:mandatoryLangCodeISO639_1> + <dcc:uniqueIdentifier>Test_DCC_Minimal</dcc:uniqueIdentifier> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>calibrationLaboratory</dcc:issuer> + <dcc:value>string-calibrationLaboratory-coreData</dcc:value> + <dcc:name> + <dcc:content lang="en">Order no.</dcc:content> + </dcc:name> + </dcc:identification> + </dcc:identifications> + <dcc:beginPerformanceDate>1957-08-13</dcc:beginPerformanceDate> + <dcc:endPerformanceDate>1957-08-13</dcc:endPerformanceDate> + <dcc:performanceLocation>laboratory</dcc:performanceLocation> + </dcc:coreData> + <dcc:items> + <dcc:item> + <dcc:name> + <dcc:content lang="de">Temperatur-Fühler</dcc:content> + <dcc:content lang="en">Temperature sensor</dcc:content> + </dcc:name> + <dcc:manufacturer> + <dcc:name> + <dcc:content>String</dcc:content> + </dcc:name> + </dcc:manufacturer> + <dcc:identifications> + <dcc:identification> + <dcc:issuer>manufacturer</dcc:issuer> + <dcc:value>string-manufacturer-item</dcc:value> + </dcc:identification> + </dcc:identifications> + </dcc:item> + </dcc:items> + <dcc:calibrationLaboratory> + <dcc:contact> + <dcc:name> + <dcc:content>Kalibrierfirma GmbH</dcc:content> + </dcc:name> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + </dcc:location> + </dcc:contact> + </dcc:calibrationLaboratory> + <dcc:respPersons> + <dcc:respPerson> + <dcc:person> + <dcc:name> + <dcc:content>Michaela Musterfrau</dcc:content> + </dcc:name> + </dcc:person> + </dcc:respPerson> + </dcc:respPersons> + <dcc:customer> + <dcc:name> + <dcc:content>Kunde GmbH</dcc:content> + </dcc:name> + <dcc:location> + <dcc:city>Musterstadt</dcc:city> + </dcc:location> + </dcc:customer> + </dcc:administrativeData> + <dcc:measurementResults> + <dcc:measurementResult> + <dcc:name> + <dcc:content lang="en">Measurement results</dcc:content> + </dcc:name> + <dcc:results> + <dcc:result refType="gp_measuringResult1"> + <dcc:name> + <dcc:content lang="de">Messergebnisse</dcc:content> + <dcc:content lang="en">Measuring results</dcc:content> + </dcc:name> + <dcc:data> + <dcc:list refType="gp_table1"> + <dcc:quantity refType="basic_referenceValue"> + <si:hybrid> + <si:realListXMLList> + <si:valueXMLList>306.248 373.121 448.253 523.319 593.154</si:valueXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> + </si:realListXMLList> + <si:realListXMLList> + <si:valueXMLList>33.098 99.971 175.103 250.169 320.004</si:valueXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> + </si:realListXMLList> + </si:hybrid> + </dcc:quantity> + </dcc:list> + </dcc:data> + </dcc:result> + </dcc:results> + </dcc:measurementResult> + </dcc:measurementResults> +</dcc:digitalCalibrationCertificate> \ No newline at end of file diff --git a/tests/Resources/example.xml.ts b/tests/resources/example.xml similarity index 93% rename from tests/Resources/example.xml.ts rename to tests/resources/example.xml index 5bacaef..e4dec5e 100644 --- a/tests/Resources/example.xml.ts +++ b/tests/resources/example.xml @@ -1,4 +1,5 @@ -const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dcc="https://ptb.de/dcc" xmlns:si="https://ptb.de/si" xsi:schemaLocation="https://ptb.de/dcc https://ptb.de/dcc/v3.1.2/dcc.xsd" schemaVersion="3.1.2"> +<?xml version="1.0" encoding="UTF-8"?> +<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dcc="https://ptb.de/dcc" xmlns:si="https://ptb.de/si" xsi:schemaLocation="https://ptb.de/dcc https://ptb.de/dcc/v3.2.0/dcc.xsd" schemaVersion="3.2.0"> <dcc:administrativeData> <dcc:dccSoftware> <dcc:software> @@ -143,7 +144,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:real> <si:value>306</si:value> - <si:unit>\\kelvin</si:unit> + <si:unit>\kelvin</si:unit> </si:real> </dcc:quantity> <dcc:quantity refType="basic_validityRangeMax"> @@ -153,7 +154,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:real> <si:value>593</si:value> - <si:unit>\\kelvin</si:unit> + <si:unit>\kelvin</si:unit> </si:real> </dcc:quantity> </dcc:data> @@ -250,7 +251,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:real> <si:value>0.1</si:value> - <si:unit>\\metre</si:unit> + <si:unit>\metre</si:unit> </si:real> </dcc:quantity> </dcc:data> @@ -272,7 +273,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:real> <si:value>293</si:value> - <si:unit>\\kelvin</si:unit> + <si:unit>\kelvin</si:unit> </si:real> </dcc:quantity> <dcc:quantity refType="basic_temperatureMax"> @@ -282,7 +283,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:real> <si:value>299</si:value> - <si:unit>\\kelvin</si:unit> + <si:unit>\kelvin</si:unit> </si:real> </dcc:quantity> </dcc:data> @@ -304,7 +305,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:real> <si:value>0.20</si:value> - <si:unit>\\one</si:unit> + <si:unit>\one</si:unit> </si:real> </dcc:quantity> <dcc:quantity refType="basic_humidityRelativeMax"> @@ -314,7 +315,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:real> <si:value>0.70</si:value> - <si:unit>\\one</si:unit> + <si:unit>\one</si:unit> </si:real> </dcc:quantity> </dcc:data> @@ -336,11 +337,11 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 <si:hybrid> <si:realListXMLList> <si:valueXMLList>306.248 373.121 448.253 523.319 593.154</si:valueXMLList> - <si:unitXMLList>\\kelvin</si:unitXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> </si:realListXMLList> <si:realListXMLList> <si:valueXMLList>33.098 99.971 175.103 250.169 320.004</si:valueXMLList> - <si:unitXMLList>\\degreecelsius</si:unitXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> </si:realListXMLList> </si:hybrid> <dcc:measurementMetaData> @@ -354,11 +355,11 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 <si:hybrid> <si:realListXMLList> <si:valueXMLList>306 373 448 523 593</si:valueXMLList> - <si:unitXMLList>\\kelvin</si:unitXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> </si:realListXMLList> <si:realListXMLList> <si:valueXMLList>32.85 99.85 174.85 249.85 319.85</si:valueXMLList> - <si:unitXMLList>\\degreecelsius</si:unitXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> </si:realListXMLList> </si:hybrid> </dcc:quantity> @@ -374,11 +375,11 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 <si:hybrid> <si:realListXMLList> <si:valueXMLList>306.32 373.21 448.36 523.31 593.07</si:valueXMLList> - <si:unitXMLList>\\kelvin</si:unitXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> </si:realListXMLList> <si:realListXMLList> <si:valueXMLList>33.17 100.06 175.21 250.16 319.92</si:valueXMLList> - <si:unitXMLList>\\degreecelsius</si:unitXMLList> + <si:unitXMLList>\degreecelsius</si:unitXMLList> </si:realListXMLList> </si:hybrid> </dcc:quantity> @@ -389,7 +390,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:realListXMLList> <si:valueXMLList>0.072 0.089 0.107 -0.009 -0.084</si:valueXMLList> - <si:unitXMLList>\\kelvin</si:unitXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> <si:expandedUncXMLList> <si:uncertaintyXMLList>0.061</si:uncertaintyXMLList> <si:coverageFactorXMLList>2</si:coverageFactorXMLList> @@ -414,7 +415,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:realListXMLList> <si:valueXMLList>-0.23 -0.23 -0.23 -0.30 -0.30</si:valueXMLList> - <si:unitXMLList>\\kelvin</si:unitXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> </si:realListXMLList> </dcc:quantity> <dcc:quantity refType="basic_acceptanceLimitUpper"> @@ -424,7 +425,7 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:name> <si:realListXMLList> <si:valueXMLList>0.23 0.23 0.23 0.30 0.30</si:valueXMLList> - <si:unitXMLList>\\kelvin</si:unitXMLList> + <si:unitXMLList>\kelvin</si:unitXMLList> </si:realListXMLList> </dcc:quantity> </dcc:data> @@ -437,7 +438,4 @@ const dcc = `<dcc:digitalCalibrationCertificate xmlns:xsi="http://www.w3.org/200 </dcc:results> </dcc:measurementResult> </dcc:measurementResults> -</dcc:digitalCalibrationCertificate>`; - -export const xml = `<?xml version="1.0" encoding="UTF-8"?> -${dcc}`; +</dcc:digitalCalibrationCertificate> \ No newline at end of file diff --git a/tests/tsconfig.json b/tests/tsconfig.json new file mode 100644 index 0000000..6ddab7a --- /dev/null +++ b/tests/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "target": "ES6", + "declaration": true, + "module": "commonjs" + }, +} diff --git a/tests/util.ts b/tests/util.ts new file mode 100644 index 0000000..cbabf5d --- /dev/null +++ b/tests/util.ts @@ -0,0 +1,36 @@ +import * as xpathTs from "xpath-ts"; +import { JSDOM } from "jsdom"; +import { DCCDocument, DCCXMLElement } from "../src"; + +export function select(xpath: string, domOrDCC: JSDOM | DCCDocument): string | number | boolean | Node | Node[] { + let dom = <JSDOM>domOrDCC; + if (domOrDCC.digitalCalibrationCertificate) { + dom = toDom(<DCCDocument>domOrDCC); + } + + return xpathTs.select(xpath, dom.window.document); +} + +export function toDom(dcc: DCCDocument) { + return new JSDOM(dcc.toXML(), { contentType: "application/xml" }); +} + +export function toTextArr(arr: DCCXMLElement[]) { + if (!arr) return []; + return arr.map((x) => x._text); +} + +export function indexOf(arr: DCCXMLElement[], el: string) { + return toTextArr(arr).indexOf(el); +} + +export function toTextContentArr(el: Element[]) { + if (!el) return []; + return el.map((x) => x.textContent); +} + +export function undefinedIfEmpty(str) { + if (!str) return undefined; + if (str.trim() === "") return undefined; + return str; +} diff --git a/tsconfig.json b/tsconfig.json index b736aad..5136c1b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,8 +3,12 @@ "target": "ES6", "module": "commonjs", "declaration": true, - "outDir": "./lib" + "sourceMap": true, + "outDir": "./lib", }, + "files": [ + "./tests/index.d.ts" + ], "include": [ "src" ], diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000000000000000000000000000000000..85098f5a364c9ba6a2170cbd50db5b8a977f019b GIT binary patch literal 202139 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⪙PH>xtGSJ5UvV= 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 ax6~8TLUCc7m7n10X>i4Z<2fxo#r_M*@9O9P literal 0 HcmV?d00001 -- GitLab