feat: implement storeGroupValue and getGroupValue with unified locator

- API Refactoring: Extracted GroupValueLocator input type to unify parameters for storeGroupValue (mutation) and getGroupValue (query).

- Data Retrieval: Implemented getGroupValue query to allow direct retrieval of JSON values stored in host groups via Zabbix Trapper items.

- Enhanced Logic: Added ZabbixGetGroupValueRequest to fetch latest history values for group-associated items.

- Improved Verification: Updated the regression suite (REG-STORE) to include a full 'Store-Update-Retrieve' verification cycle.

- Documentation:

    - Updated docs/howtos/cookbook.md recipes to use the new locator structure and getGroupValue for verification.

    - Updated sample query files (docs/queries/) with corrected variables and verification queries.

- Tests:

    - Added unit and integration tests for getGroupValue.

    - Updated existing tests to match the refactored storeGroupValue schema.

- Verification: Verified 100% pass rate for all 16 regression steps and all unit/integration tests.
This commit is contained in:
Andreas Hilbig 2026-02-20 00:24:05 +01:00
parent 8f00082c6a
commit ce340ccf2e
27 changed files with 2788 additions and 228 deletions

View file

@ -25,7 +25,7 @@ Guide on code generation (GraphQL Codegen), running Jest tests, and local Docker
### 💻 [Local Development Environment](./local_development.md)
Detailed instructions for setting up a fully isolated local development environment with Zabbix using Docker Compose.
### 🧪 [Test Specification](../tests.md)
### 🧪 [Test Specification](../testcases/tests.md)
Detailed list of test cases, categories (Unit, Integration, E2E), and coverage checklist.
### 🤖 [MCP & Agent Integration](./mcp.md)

View file

@ -139,6 +139,12 @@ Execute the `importTemplates` mutation to create the template and items automati
> **Reference**: Use the [Sample: Distance Tracker Import](../queries/sample_import_distance_tracker_template.graphql) for a complete mutation and variables example.
### ✅ Step 4: Verify the Extension
#### Automated Regression Test
Parts of this functionality are covered by the regression suite. To run it:
- Execute the `runAllRegressionTests` mutation.
- Check the step `REG-STATE: State sub-properties retrieval (indirect dependency)`.
#### Manual Verification
Verify that the new type is available and correctly mapped by creating a test host and querying it.
#### 1. Create a Test Host
@ -299,6 +305,16 @@ Use the `importTemplates` mutation to create the template. Use **HTTP agent** or
- Description: The average ground value (Bodenrichtwert) extracted from the BORIS NRW GeoJSON response.
### ✅ Step 5: Verification
#### Automated Regression Test
Parts of this functionality are covered by the regression suite. To run it:
- Execute the `runAllRegressionTests` mutation.
- Check the following steps:
- REG-HTTP: HTTP Agent URL support
- REG-DEP: Dependent Items support
- REG-ITEM-META: Item metadata (preprocessing, units, description, error)
- REG-STATE: State sub-properties retrieval (indirect dependency)
#### Manual Verification
Create a host, assign it macros for coordinates, and query its state.
1. **Create Host (Weather Example)**:
@ -401,6 +417,12 @@ Push GeoJSON data to your simulated device using the `pushHistory` mutation. Thi
> **Reference**: See the [Sample: Push GeoJSON History](../queries/sample_push_geojson_history.graphql) for a complete example of pushing historical data.
### ✅ Step 5: Verification
#### Automated Regression Test
Covered by the automated regression test suite. To run it:
1. Execute the `runAllRegressionTests` mutation.
2. Check for the step `REG-PUSH: pushHistory mutation`.
#### Manual Verification
Verify that the device correctly resolves to the new type and that both the current state and historical data are accessible.
- **Create Host**: Use the `importHosts` mutation to create a host (e.g. `Vehicle1`) and link it to the simulated template.
@ -448,6 +470,14 @@ This recipe shows how to execute a comprehensive query to verify the state and c
Execute the query against your GraphQL endpoint. This query retrieves information from `allHostGroups`, `allDevices`, and `allHosts`, using inline fragments to access fields specific to `DistanceTrackerDevice`.
### ✅ Step 3: Verification
#### Automated Regression Test
Parts of this functionality are covered by the regression suite. To run it:
- Execute the `runAllRegressionTests` mutation.
- Check the following steps:
- REG-STATE: State sub-properties retrieval (indirect dependency)
- REG-DEV-FILTER: allDevices deviceType filter
#### Manual Verification
Check the response for the following:
- **apiVersion** and **zabbixVersion** are returned.
- **allHostGroups** contains the expected groups.
@ -482,6 +512,12 @@ mutation CreateNewHost($host: String!, $groups: [Int!]!, $templates: [Int], $tem
```
### ✅ Step 3: Verify Host Creation
#### Automated Regression Test
Covered by the automated regression test suite. To run it:
1. Execute the `runAllRegressionTests` mutation.
2. Check for the step `REG-HOST: Host retrieval and visibility (incl. groups and templates)`.
#### Manual Verification
Check if the host is correctly provisioned and linked to groups:
```graphql
query VerifyHost($host: String!) {
@ -565,6 +601,170 @@ For detailed examples of the input structures, refer to [Sample Import Templates
---
## 🍳 Recipe: Storing Configuration in a Host Group
This recipe demonstrates how to store a JSON-based configuration or state object and associate it with a host group. This is useful for managing application settings, device configurations, or any other metadata that needs to be persisted in Zabbix and retrieved via GraphQL.
### 📋 Prerequisites
- Zabbix GraphQL API is running.
- A host group exists where the configuration should be stored (e.g. `Infrastructure/Configurations`).
### 🛠️ Step 1: Preparation/Definition
Identify the target host group name and the configuration data you want to store.
### ⚙️ Step 2: Configuration/Settings
No additional Zabbix configuration is required. The API will automatically handle host and item creation if they don't exist.
### 🚀 Step 3: Execution/Action
Execute the `storeGroupValue` mutation. The API will:
- Look for a host in the group with the tag `valueType` matching your `valueType` argument.
- If not found, create a new host with that tag.
- Ensure a Zabbix Trapper item with your `key` exists on that host.
- Push the JSON `value` to that item.
```graphql
mutation StoreConfig($locator: GroupValueLocator!, $config: JSONObject!) {
storeGroupValue(
locator: $locator,
value: $config
) {
itemid
error { message }
}
}
```
- *Variables*:
```json
{
"locator": {
"groupName": "Infrastructure/Configurations",
"valueType": "GlobalSettings",
"key": "api.config.json"
},
"config": {
"maintenanceMode": false,
"logLevel": "DEBUG",
"updatedAt": "2024-05-20T10:00:00Z"
}
}
```
### ✅ Step 4: Verification
Verify the stored value by querying the host and its items.
#### Automated Regression Test
The functionality is covered by the automated regression test suite. To run it:
1. Execute the `runAllRegressionTests` mutation.
2. Check for the step `REG-STORE: storeGroupValue mutation`.
#### Manual Verification
You can verify the stored value using the `getGroupValue` query:
```graphql
query GetConfig($locator: GroupValueLocator!) {
getGroupValue(locator: $locator)
}
```
Alternatively, verify by querying the host and its items:
```graphql
query VerifyConfig($pattern: String!) {
allHosts(name_pattern: $pattern) {
host
... on ZabbixHost {
tags
}
items {
name
key_
lastvalue
}
}
}
```
---
## 🍳 Recipe: Retrieving Stored Group Values
This recipe shows how to retrieve a JSON-based configuration or state object previously stored using the `storeGroupValue` mutation.
### 📋 Prerequisites
- Zabbix GraphQL API is running.
- A value has been stored using the `storeGroupValue` mutation.
### 🛠️ Step 1: Preparation/Definition
Identify the locator parameters used when the value was stored:
- `groupName` or `groupid`
- `valueType`
- `key`
### 🚀 Step 2: Execution/Action
Execute the `getGroupValue` query.
```graphql
query GetStoredConfig($locator: GroupValueLocator!) {
getGroupValue(locator: $locator)
}
```
- *Variables*:
```json
{
"locator": {
"groupName": "Infrastructure/Configurations",
"valueType": "GlobalSettings",
"key": "api.config.json"
}
}
```
### ✅ Step 3: Verification
The query will return the stored JSON object as the result. If no matching value is found, `null` is returned.
---
## 🍳 Recipe: Creating a GeoJSON Feature Collection for Cologne Trade Fair Parking
This recipe shows how to persist a GeoJSON `FeatureCollection` using the `storeGroupValue` mutation. As a concrete example, we store the areas of parking lots belonging to the Cologne Trade Fair (Koelnmesse) under the host group `Roadwork/CologneTradeFair`. Each feature represents a parking lot polygon and includes descriptive metadata (e.g. name, type, operator) derived from public sources (e.g. OpenStreetMap).
### 📋 Prerequisites
- Zabbix GraphQL API is running.
- You have a valid Zabbix user/session or token.
- The base host group prefix `Roadwork` exists.
- The subgroup `Roadwork/CologneTradeFair` exists. If it does not exist, create it manually first (via the `importHostGroups` mutation or in the Zabbix UI).
### 🛠️ Step 1: Preparation/Definition
Prepare a GeoJSON `FeatureCollection` with one feature per parking lot. Include descriptive metadata (e.g. name, type, operator) derived from public sources like OpenStreetMap.
> **Reference**: For a complete sample `FeatureCollection` including parking lot "P22", see [Sample: Store Parking GeoJSON](../queries/sample_store_parking_geojson.graphql).
- *Note*: Coordinates used in the samples are illustrative and simplified for documentation. For production, use the most accurate polygons available from authoritative or open data sources.
### ⚙️ Step 2: Configuration/Settings
- Manually ensure the host group `Roadwork/CologneTradeFair` exists (see Prerequisites).
- The API will automatically:
- Create (or reuse) a storage host in that group tagged with `valueType=FeatureCollection`.
- Create (or update) a Zabbix Trapper item with key `geometry.areas.parking` on that host.
### 🚀 Step 3: Execution/Action
Execute the `storeGroupValue` mutation to store the `FeatureCollection` in Zabbix.
> **Reference**: Use the [Sample: Store Parking GeoJSON](../queries/sample_store_parking_geojson.graphql) for the complete mutation and variables JSON.
### ✅ Step 4: Verification
Verify the stored value using the `getGroupValue` query or by querying the host and its items.
> **Reference**: Use the **Verification Query** from [Sample: Store Parking GeoJSON](../queries/sample_store_parking_geojson.graphql).
- *Automated Regression Test*: This functionality is covered by the regression suite. To run it:
- Execute the `runAllRegressionTests` mutation.
- Check for the step `REG-STORE: storeGroupValue mutation`.
---
## 🍳 Recipe: Running the Smoketest via MCP
This recipe explains how to execute the end-to-end smoketest using the integrated MCP server. This is the fastest way to verify that your Zabbix GraphQL API is correctly connected to a Zabbix instance and all core features (Groups, Templates, Hosts) are working.
@ -725,6 +925,12 @@ mutation PushDeviceData($host: String, $key: String, $itemid: Int, $values: [His
```
### ✅ Step 3: Verification
#### Automated Regression Test
The functionality is covered by the automated regression test suite. To run it:
1. Execute the `runAllRegressionTests` mutation.
2. Check for the step `REG-PUSH: pushHistory mutation`.
#### Manual Verification
Verify that the data was successfully pushed by querying the item's last value:
```graphql

View file

@ -40,7 +40,7 @@ For running integration tests against a real Zabbix instance, it is recommended
#### Adding New Tests
- **Location**: Place new test files in `src/test/` with the `.test.ts` extension.
- **Coverage**: Ensure you cover both successful operations and error scenarios.
- **Test Specification**: Every new test must be documented in the [Test Specification](../tests.md).
- **Test Specification**: Every new test must be documented in the [Test Specification](../testcases/tests.md).
- **Best Practice**: If you find a bug, first create a reproduction test in `src/test/` to verify the fix.
## 🔄 Updating Dependencies

View file

@ -0,0 +1,9 @@
mutation StoreConfiguration($locator: GroupValueLocator!, $value: JSONObject!) {
storeGroupValue(
locator: $locator,
value: $value
) {
itemid
error { message }
}
}

View file

@ -0,0 +1,70 @@
### Mutation
Store a GeoJSON `FeatureCollection` for Cologne Trade Fair parking lots using the `storeGroupValue` mutation.
```graphql
mutation StoreParkingGeoJSON($locator: GroupValueLocator!, $value: JSONObject!) {
storeGroupValue(locator: $locator, value: $value) {
itemid
error { message }
}
}
```
### Variables
```json
{
"locator": {
"groupName": "Roadwork/CologneTradeFair",
"valueType": "FeatureCollection",
"key": "geometry.areas.parking"
},
"value": {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "name": "P22", "type": "parking lot", "operator": "Koelnmesse", "ref": "P22", "source": "OpenStreetMap", "website": "https://www.koelnmesse.de/", "updatedAt": "2026-02-19T00:00:00Z" },
"geometry": { "type": "Polygon", "coordinates": [[[6.9812, 50.9469], [6.9823, 50.9467], [6.9820, 50.9459], [6.9810, 50.9461], [6.9812, 50.9469]]] }
},
{
"type": "Feature",
"properties": { "name": "P21", "type": "parking lot", "operator": "Koelnmesse", "ref": "P21", "source": "OpenStreetMap" },
"geometry": { "type": "Polygon", "coordinates": [[[6.9800, 50.9476], [6.9810, 50.9473], [6.9809, 50.9468], [6.9798, 50.9470], [6.9800, 50.9476]]] }
},
{
"type": "Feature",
"properties": { "name": "P32", "type": "parking lot", "operator": "Koelnmesse", "ref": "P32", "source": "OpenStreetMap" },
"geometry": { "type": "Polygon", "coordinates": [[[6.9835, 50.9438], [6.9843, 50.9436], [6.9841, 50.9430], [6.9833, 50.9432], [6.9835, 50.9438]]] }
}
]
}
}
```
### Verification Query
Verify the stored GeoJSON using the `getGroupValue` query.
```graphql
query VerifyParkingGeoJSON($locator: GroupValueLocator!) {
getGroupValue(locator: $locator)
}
```
Alternatively, verify by querying the host and its items:
```graphql
query VerifyParkingGeoJSONAlt($hostPattern: String!) {
allHosts(name_pattern: $hostPattern) {
host
... on ZabbixHost {
tags
}
items {
name
key_
lastvalue
lastclock
}
}
}
```

View file

@ -0,0 +1,7 @@
# Test Cases: storeGroupValue (Moved)
This content has been consolidated into the main Test Specification document.
- New location: [docs/testcases/tests.md#store-group-value-storegroupvalue-test-cases](./tests.md#store-group-value-storegroupvalue-test-cases)
Please update any references to this file.

179
docs/testcases/tests.md Normal file
View file

@ -0,0 +1,179 @@
# Test Specification
This document outlines the test cases and coverage for the Zabbix GraphQL API.
## 📂 Test Categories
- **Unit Tests**: Verify individual functions, classes, or logic in isolation. All external dependencies (Zabbix API, Config) are mocked to ensure the test is fast and deterministic. These tests are executed on each build.
- *Reference*: `src/test/host_importer.test.ts`, `src/test/template_query.test.ts`
- **Integration Tests**: Test the interaction between multiple internal components. Typically, these tests use a mock Apollo Server to execute actual GraphQL operations against the resolvers and data sources, with the Zabbix API mocked at the network layer. These tests are executed on each build.
- *Reference*: `src/test/host_integration.test.ts`, `src/test/user_rights_integration.test.ts`
- **End-to-End (E2E) Tests**: Validate complete, multi-step business workflows from start to finish (e.g., a full import-verify-cleanup cycle). These tests are executed against a real, running Zabbix instance to ensure the entire system achieves the desired business outcome. These tests are triggered after startup or on demand via GraphQL/MCP endpoints.
- *Reference*: `mcp/operations/runSmoketest.graphql` (executed via MCP)
## 🧪 Test Case Definitions
### Host Management
- **TC-HOST-01**: Query all hosts using sample query.
- **TC-HOST-02**: Import hosts using sample mutation.
- **TC-HOST-03**: Import host groups and create new hierarchy.
- **TC-HOST-04**: Import basic host.
- **TC-HOST-05**: Query all hosts with name pattern.
- **TC-HOST-06**: Query all devices by host ID.
- **TC-HOST-07**: Query all host groups with search pattern.
- **TC-HOST-08**: Query host groups using default search pattern.
- **TC-HOST-09**: Query locations.
### Template Management
- **TC-TEMP-01**: Import templates using sample query and variables.
- **TC-TEMP-02**: Import and export templates comparison.
- **TC-TEMP-03**: Import and export template groups comparison.
- **TC-TEMP-04**: Query all templates.
- **TC-TEMP-05**: Filter templates by host IDs.
- **TC-TEMP-06**: Filter templates by name pattern.
- **TC-TEMP-07**: Filter templates by name pattern with wildcard.
- **TC-TEMP-08**: Import template groups (new group).
- **TC-TEMP-09**: Import template groups (existing group).
- **TC-TEMP-10**: Import basic template.
- **TC-TEMP-11**: Import templates with items, linked templates, and dependent items.
- **TC-TEMP-12**: Import templates query validation.
- **TC-TEMP-13**: Import templates error handling (data field inclusion).
- **TC-TEMP-14**: Delete templates successfully.
- **TC-TEMP-15**: Delete templates error handling.
- **TC-TEMP-16**: Delete templates by name pattern.
- **TC-TEMP-17**: Delete templates with merged IDs and name pattern.
- **TC-TEMP-18**: Delete template groups successfully.
- **TC-TEMP-19**: Delete template groups error handling.
- **TC-TEMP-20**: Delete template groups by name pattern.
### User Rights and Permissions
- **TC-AUTH-01**: Export user rights.
- **TC-AUTH-02**: Query user permissions.
- **TC-AUTH-03**: Check if user has permissions.
- **TC-AUTH-04**: Import user rights.
- **TC-AUTH-05**: Import user rights using sample mutation.
### History and Data Pushing
- **TC-HIST-01**: Push history data using `pushHistory` mutation.
### Query Optimization
- **TC-OPT-01**: Verify that GraphQL queries only fetch requested fields from Zabbix (reduced output).
- **TC-OPT-02**: Verify that skippable Zabbix parameters (like selectItems) are omitted if not requested in GraphQL.
- **TC-OPT-03**: Verify that indirect dependencies (e.g., `state` requiring `items`) are correctly handled by the optimization logic.
### System and Configuration
- **TC-CONF-01**: Schema loader uses Config variables.
- **TC-CONF-02**: Zabbix API constants derived from Config.
- **TC-CONF-03**: Logger levels initialized from Config.
- **TC-CONF-04**: API version query.
- **TC-CONF-05**: Login query.
- **TC-CONF-06**: Logout query.
- **TC-CONF-07**: Parse Zabbix arguments.
### Documentation and MCP
- **TC-DOCS-01**: Validate all Zabbix documentation sample queries.
- **TC-MCP-01**: Validate all MCP operation files against the schema.
### Schema-dependent Tests
- **TC-SCHEMA-01**: Verify comprehensive query for `DistanceTrackerDevice` works correctly when schema is extended.
### End-to-End (E2E) Tests
- **TC-E2E-01**: Run a complete smoketest using MCP (creates template, group, and host, verifies, and cleans up).
- **TC-E2E-02**: Run all regression tests to verify critical system behavior and prevent known issues.
#### Currently Contained Regression Tests
The `runAllRegressionTests` mutation (TC-E2E-02) executes the following checks:
- **Host without items**: Verifies that hosts created without any items or linked templates can be successfully queried by the system. This ensures that the hierarchical mapping and resolvers handle empty item lists gracefully.
- **Locations query argument order**: Verifies that the `locations` query correctly handles its parameters and successfully contacts the Zabbix API without session errors (verifying the fix for argument order in the resolver).
- **Template technical name lookup**: Verifies that templates can be correctly identified by their technical name (`host` field) when linking them to hosts during import.
- **HTTP Agent URL support**: Verifies that templates containing HTTP Agent items with a configured URL can be imported successfully (verifying the addition of the `url` field to `CreateTemplateItem`).
- **Host retrieval and visibility**: Verifies that newly imported hosts are immediately visible and retrievable via the `allHosts` query, including correctly delivered assigned templates and assigned host groups (verifying the fix for `output` fields in the host query data source).
- **Query Optimization**: Verifies that GraphQL requests correctly translate into optimized Zabbix parameters, reducing the amount of data fetched (verifying the query optimization feature).
- **Empty result handling**: Verifies that queries return an empty array instead of an error when no entities match the provided filters.
- **Dependent Items**: Verifies that templates with master and dependent items can be imported successfully, correctly resolving the dependency within the same import operation.
- **State sub-properties**: Verifies that requesting device state sub-properties correctly triggers the retrieval of required Zabbix items, even if `items` is not explicitly requested (verifying the indirect dependency logic).
- **Negative Optimization (allDevices)**: Verifies that items are NOT requested from Zabbix if neither `items` nor `state` (or state sub-properties) are requested within the `allDevices` query.
- **allDevices deviceType filter**: Verifies that the `allDevices` query only returns hosts that have a `deviceType` tag, and that the `deviceType` field is populated for all results.
- **pushHistory mutation**: Verifies that the `pushHistory` mutation correctly pushes data to ZABBIX_TRAP items, using either item ID or a combination of host and item key.
### Store Group Value (storeGroupValue)
- **TC-SGV-01 (Unit)**: Input validation — missing `valueType` when neither `host` nor `itemid` is provided. Covered by `src/test/store_group_value.unit.test.ts`.
- **TC-SGV-02 (Unit)**: Input validation — missing `groupid`/`groupName` when `host` is not provided. Covered by `src/test/store_group_value.unit.test.ts`.
- **TC-SGV-03 (Unit)**: Group lookup failure — `groupName` not found. Covered by `src/test/store_group_value.unit.test.ts`.
- **TC-SGV-04 (Unit)**: Automated host creation when no host with the `valueType` tag exists in the group. Covered by `src/test/store_group_value.unit.test.ts`.
- **TC-SGV-05 (Integration)**: Full `storeGroupValue` mutation flow with mocked Zabbix API. Covered by `src/test/store_group_value.integration.test.ts`.
- **TC-SGV-06 (Unit)**: Different keys result in different item lookups for the same storage host. Covered by `src/test/store_group_value.unit.test.ts`.
- **REG-STORE-1 (E2E/Regression)**: Group name resolution to `groupid`. Implemented in `src/execution/regression_test_executor.ts` (step: `REG-STORE: storeGroupValue mutation`).
- **REG-STORE-2 (E2E/Regression)**: Auto-provision storage host with `valueType` tag if absent. Implemented in `src/execution/regression_test_executor.ts`.
- **REG-STORE-3 (E2E/Regression)**: Idempotent update — same `key` updates existing item instead of creating a new one. Implemented in `src/execution/regression_test_executor.ts`.
- **REG-STORE-4 (E2E/Regression)**: Different keys result in different items on the same storage host. Implemented in `src/execution/regression_test_executor.ts`.
- **REG-STORE-5 (E2E/Regression)**: Value retrieval — verify that `getGroupValue` correctly retrieves the stored JSON data. Implemented in `src/execution/regression_test_executor.ts`.
- **REG-STORE-6 (E2E/Regression)**: Cleanup — delete created storage host and any host group(s) that were created by the test run (pre-existing groups are preserved). Implemented in `src/execution/regression_test_executor.ts`.
## ✅ Test Coverage Checklist
| ID | Test Case | Category | Technology | Code Link |
|:---|:---|:---|:---|:---|
| TC-HOST-01 | Query allHosts using sample | Integration | Jest | [src/test/host_integration.test.ts](../../src/test/host_integration.test.ts) |
| TC-HOST-02 | Import hosts using sample | Integration | Jest | [src/test/host_integration.test.ts](../../src/test/host_integration.test.ts) |
| TC-HOST-03 | importHostGroups - create new hierarchy | Unit | Jest | [src/test/host_importer.test.ts](../../src/test/host_importer.test.ts) |
| TC-HOST-04 | importHosts - basic host | Unit | Jest | [src/test/host_importer.test.ts](../../src/test/host_importer.test.ts) |
| TC-HOST-05 | allHosts query | Unit | Jest | [src/test/host_query.test.ts](../../src/test/host_query.test.ts) |
| TC-HOST-06 | allDevices query | Unit | Jest | [src/test/host_query.test.ts](../../src/test/host_query.test.ts) |
| TC-HOST-07 | allHostGroups query | Unit | Jest | [src/test/host_query.test.ts](../../src/test/host_query.test.ts) |
| TC-HOST-08 | allHostGroups query - default pattern | Unit | Jest | [src/test/host_query.test.ts](../../src/test/host_query.test.ts) |
| TC-HOST-09 | locations query | Unit | Jest | [src/test/host_query.test.ts](../../src/test/host_query.test.ts) |
| TC-TEMP-01 | Import templates using sample | Integration | Jest | [src/test/template_integration.test.ts](../../src/test/template_integration.test.ts) |
| TC-TEMP-02 | Import and Export templates comparison | Integration | Jest | [src/test/template_integration.test.ts](../../src/test/template_integration.test.ts) |
| TC-TEMP-03 | Import and Export template groups comparison | Integration | Jest | [src/test/template_integration.test.ts](../../src/test/template_integration.test.ts) |
| TC-TEMP-04 | templates query - returns all | Unit | Jest | [src/test/template_query.test.ts](../../src/test/template_query.test.ts) |
| TC-TEMP-05 | templates query - filters by hostids | Unit | Jest | [src/test/template_query.test.ts](../../src/test/template_query.test.ts) |
| TC-TEMP-06 | templates query - filters by name_pattern | Unit | Jest | [src/test/template_query.test.ts](../../src/test/template_query.test.ts) |
| TC-TEMP-07 | templates query - name_pattern wildcard | Unit | Jest | [src/test/template_query.test.ts](../../src/test/template_query.test.ts) |
| TC-TEMP-08 | importTemplateGroups - create new | Unit | Jest | [src/test/template_importer.test.ts](../../src/test/template_importer.test.ts) |
| TC-TEMP-09 | importTemplateGroups - group exists | Unit | Jest | [src/test/template_importer.test.ts](../../src/test/template_importer.test.ts) |
| TC-TEMP-10 | importTemplates - basic template | Unit | Jest | [src/test/template_importer.test.ts](../../src/test/template_importer.test.ts) |
| TC-TEMP-11 | importTemplates - complex template | Unit | Jest | [src/test/template_importer.test.ts](../../src/test/template_importer.test.ts) |
| TC-TEMP-12 | importTemplates - template query | Unit | Jest | [src/test/template_importer.test.ts](../../src/test/template_importer.test.ts) |
| TC-TEMP-13 | importTemplates - error data field | Unit | Jest | [src/test/template_importer.test.ts](../../src/test/template_importer.test.ts) |
| TC-TEMP-14 | deleteTemplates - success | Unit | Jest | [src/test/template_deleter.test.ts](../../src/test/template_deleter.test.ts) |
| TC-TEMP-15 | deleteTemplates - error | Unit | Jest | [src/test/template_deleter.test.ts](../../src/test/template_deleter.test.ts) |
| TC-TEMP-16 | deleteTemplates - by name_pattern | Unit | Jest | [src/test/template_deleter.test.ts](../../src/test/template_deleter.test.ts) |
| TC-TEMP-17 | deleteTemplates - merged IDs | Unit | Jest | [src/test/template_deleter.test.ts](../../src/test/template_deleter.test.ts) |
| TC-TEMP-18 | deleteTemplateGroups - success | Unit | Jest | [src/test/template_deleter.test.ts](../../src/test/template_deleter.test.ts) |
| TC-TEMP-19 | deleteTemplateGroups - error | Unit | Jest | [src/test/template_deleter.test.ts](../../src/test/template_deleter.test.ts) |
| TC-TEMP-20 | deleteTemplateGroups - by name_pattern | Unit | Jest | [src/test/template_deleter.test.ts](../../src/test/template_deleter.test.ts) |
| TC-AUTH-01 | exportUserRights query | Unit | Jest | [src/test/user_rights.test.ts](../../src/test/user_rights.test.ts) |
| TC-AUTH-02 | userPermissions query | Unit | Jest | [src/test/user_rights.test.ts](../../src/test/user_rights.test.ts) |
| TC-AUTH-03 | hasPermissions query | Unit | Jest | [src/test/user_rights.test.ts](../../src/test/user_rights.test.ts) |
| TC-AUTH-04 | importUserRights mutation | Unit | Jest | [src/test/user_rights.test.ts](../../src/test/user_rights.test.ts) |
| TC-AUTH-05 | Import user rights using sample | Integration | Jest | [src/test/user_rights_integration.test.ts](../../src/test/user_rights_integration.test.ts) |
| TC-OPT-01 | Verify Query Optimization (reduced output) | Unit/E2E | Jest/Regression | [src/test/query_optimization.test.ts](../../src/test/query_optimization.test.ts) |
| TC-OPT-02 | Verify skippable parameters | Unit/E2E | Jest/Regression | [src/test/query_optimization.test.ts](../../src/test/query_optimization.test.ts) |
| TC-OPT-03 | Verify indirect dependencies | Unit | Jest | [src/test/indirect_dependencies.test.ts](../../src/test/indirect_dependencies.test.ts) |
| TC-CONF-01 | schema_loader uses Config variables | Unit | Jest | [src/test/schema_config.test.ts](../../src/test/schema_config.test.ts) |
| TC-CONF-02 | constants are derived from Config | Unit | Jest | [src/test/zabbix_api_config.test.ts](../../src/test/zabbix_api_config.test.ts) |
| TC-CONF-03 | logger levels initialized from Config | Unit | Jest | [src/test/logger_config.test.ts](../../src/test/logger_config.test.ts) |
| TC-CONF-04 | apiVersion query | Unit | Jest | [src/test/misc_resolvers.test.ts](../../src/test/misc_resolvers.test.ts) |
| TC-CONF-05 | login query | Unit | Jest | [src/test/misc_resolvers.test.ts](../../src/test/misc_resolvers.test.ts) |
| TC-CONF-06 | logout query | Unit | Jest | [src/test/misc_resolvers.test.ts](../../src/test/misc_resolvers.test.ts) |
| TC-CONF-07 | Parse Zabbix Args | Unit | Jest | [src/test/zabbix_api_args_parser.test.ts](../../src/test/zabbix_api_args_parser.test.ts) |
| TC-DOCS-01 | Zabbix Docs Samples Integration | Integration | Jest | [src/test/zabbix_docs_samples.test.ts](../../src/test/zabbix_docs_samples.test.ts) |
| TC-MCP-01 | MCP Operations Validation | Integration | Jest | [src/test/mcp_operations_validation.test.ts](../../src/test/mcp_operations_validation.test.ts) |
| TC-SCHEMA-01 | DistanceTrackerDevice Query | Integration | Jest | [src/test/schema_dependent_queries.test.ts](../../src/test/schema_dependent_queries.test.ts) |
| TC-SGV-05 | storeGroupValue Integration | Integration | Jest | [src/test/store_group_value.integration.test.ts](../../src/test/store_group_value.integration.test.ts) |
| TC-SGV-06 | storeGroupValue different keys | Unit | Jest | [src/test/store_group_value.unit.test.ts](../../src/test/store_group_value.unit.test.ts) |
| TC-SGV-07 | getGroupValue unit test | Unit | Jest | [src/test/store_group_value.unit.test.ts](../../src/test/store_group_value.unit.test.ts) |
| TC-SGV-08 | getGroupValue Integration | Integration | Jest | [src/test/store_group_value.integration.test.ts](../../src/test/store_group_value.integration.test.ts) |
| TC-E2E-01 | Run complete smoketest | E2E | GraphQL / MCP | [mcp/operations/runSmoketest.graphql](../../mcp/operations/runSmoketest.graphql) |
| TC-E2E-02 | Run all regression tests | E2E | GraphQL / MCP | [mcp/operations/runAllRegressionTests.graphql](../../mcp/operations/runAllRegressionTests.graphql) |
## 📝 Test Case Obligations
As per project guidelines, every new feature or bug fix must be accompanied by a described test case in this specification.
- **Feature**: A new feature must have a corresponding test case (TC) defined before implementation.
- **Bug Fix**: A bug fix must include a reproduction test case that fails without the fix and passes with it. Additionally, a permanent regression test must be added to the automated suite (e.g., `RegressionTestExecutor`) to prevent the issue from re-occurring.
- **Documentation**: The `docs/testcases/tests.md` file must be updated to reflect any changes in test coverage.
- **Categorization**: Tests must be categorized as Unit, Integration, or End-to-End (E2E).

View file

@ -1,160 +1,7 @@
# Test Specification
# Test Specification (Moved)
This document outlines the test cases and coverage for the Zabbix GraphQL API.
This document has moved. Please use the consolidated location:
## 📂 Test Categories
- [docs/testcases/tests.md](./testcases/tests.md)
- **Unit Tests**: Verify individual functions, classes, or logic in isolation. All external dependencies (Zabbix API, Config) are mocked to ensure the test is fast and deterministic. These tests are executed on each build.
- *Reference*: `src/test/host_importer.test.ts`, `src/test/template_query.test.ts`
- **Integration Tests**: Test the interaction between multiple internal components. Typically, these tests use a mock Apollo Server to execute actual GraphQL operations against the resolvers and data sources, with the Zabbix API mocked at the network layer. These tests are executed on each build.
- *Reference*: `src/test/host_integration.test.ts`, `src/test/user_rights_integration.test.ts`
- **End-to-End (E2E) Tests**: Validate complete, multi-step business workflows from start to finish (e.g., a full import-verify-cleanup cycle). These tests are executed against a real, running Zabbix instance to ensure the entire system achieves the desired business outcome. These tests are triggered after startup or on demand via GraphQL/MCP endpoints.
- *Reference*: `mcp/operations/runSmoketest.graphql` (executed via MCP)
## 🧪 Test Case Definitions
### Host Management
- **TC-HOST-01**: Query all hosts using sample query.
- **TC-HOST-02**: Import hosts using sample mutation.
- **TC-HOST-03**: Import host groups and create new hierarchy.
- **TC-HOST-04**: Import basic host.
- **TC-HOST-05**: Query all hosts with name pattern.
- **TC-HOST-06**: Query all devices by host ID.
- **TC-HOST-07**: Query all host groups with search pattern.
- **TC-HOST-08**: Query host groups using default search pattern.
- **TC-HOST-09**: Query locations.
### Template Management
- **TC-TEMP-01**: Import templates using sample query and variables.
- **TC-TEMP-02**: Import and export templates comparison.
- **TC-TEMP-03**: Import and export template groups comparison.
- **TC-TEMP-04**: Query all templates.
- **TC-TEMP-05**: Filter templates by host IDs.
- **TC-TEMP-06**: Filter templates by name pattern.
- **TC-TEMP-07**: Filter templates by name pattern with wildcard.
- **TC-TEMP-08**: Import template groups (new group).
- **TC-TEMP-09**: Import template groups (existing group).
- **TC-TEMP-10**: Import basic template.
- **TC-TEMP-11**: Import templates with items, linked templates, and dependent items.
- **TC-TEMP-12**: Import templates query validation.
- **TC-TEMP-13**: Import templates error handling (data field inclusion).
- **TC-TEMP-14**: Delete templates successfully.
- **TC-TEMP-15**: Delete templates error handling.
- **TC-TEMP-16**: Delete templates by name pattern.
- **TC-TEMP-17**: Delete templates with merged IDs and name pattern.
- **TC-TEMP-18**: Delete template groups successfully.
- **TC-TEMP-19**: Delete template groups error handling.
- **TC-TEMP-20**: Delete template groups by name pattern.
### User Rights and Permissions
- **TC-AUTH-01**: Export user rights.
- **TC-AUTH-02**: Query user permissions.
- **TC-AUTH-03**: Check if user has permissions.
- **TC-AUTH-04**: Import user rights.
- **TC-AUTH-05**: Import user rights using sample mutation.
### History and Data Pushing
- **TC-HIST-01**: Push history data using `pushHistory` mutation.
### Query Optimization
- **TC-OPT-01**: Verify that GraphQL queries only fetch requested fields from Zabbix (reduced output).
- **TC-OPT-02**: Verify that skippable Zabbix parameters (like selectItems) are omitted if not requested in GraphQL.
- **TC-OPT-03**: Verify that indirect dependencies (e.g., `state` requiring `items`) are correctly handled by the optimization logic.
### System and Configuration
- **TC-CONF-01**: Schema loader uses Config variables.
- **TC-CONF-02**: Zabbix API constants derived from Config.
- **TC-CONF-03**: Logger levels initialized from Config.
- **TC-CONF-04**: API version query.
- **TC-CONF-05**: Login query.
- **TC-CONF-06**: Logout query.
- **TC-CONF-07**: Parse Zabbix arguments.
### Documentation and MCP
- **TC-DOCS-01**: Validate all Zabbix documentation sample queries.
- **TC-MCP-01**: Validate all MCP operation files against the schema.
### Schema-dependent Tests
- **TC-SCHEMA-01**: Verify comprehensive query for `DistanceTrackerDevice` works correctly when schema is extended.
### End-to-End (E2E) Tests
- **TC-E2E-01**: Run a complete smoketest using MCP (creates template, group, and host, verifies, and cleans up).
- **TC-E2E-02**: Run all regression tests to verify critical system behavior and prevent known issues.
#### Currently Contained Regression Tests
The `runAllRegressionTests` mutation (TC-E2E-02) executes the following checks:
- **Host without items**: Verifies that hosts created without any items or linked templates can be successfully queried by the system. This ensures that the hierarchical mapping and resolvers handle empty item lists gracefully.
- **Locations query argument order**: Verifies that the `locations` query correctly handles its parameters and successfully contacts the Zabbix API without session errors (verifying the fix for argument order in the resolver).
- **Template technical name lookup**: Verifies that templates can be correctly identified by their technical name (`host` field) when linking them to hosts during import.
- **HTTP Agent URL support**: Verifies that templates containing HTTP Agent items with a configured URL can be imported successfully (verifying the addition of the `url` field to `CreateTemplateItem`).
- **Host retrieval and visibility**: Verifies that newly imported hosts are immediately visible and retrievable via the `allHosts` query, including correctly delivered assigned templates and assigned host groups (verifying the fix for `output` fields in the host query data source).
- **Query Optimization**: Verifies that GraphQL requests correctly translate into optimized Zabbix parameters, reducing the amount of data fetched (verifying the query optimization feature).
- **Empty result handling**: Verifies that queries return an empty array instead of an error when no entities match the provided filters.
- **Dependent Items**: Verifies that templates with master and dependent items can be imported successfully, correctly resolving the dependency within the same import operation.
- **State sub-properties**: Verifies that requesting device state sub-properties correctly triggers the retrieval of required Zabbix items, even if `items` is not explicitly requested (verifying the indirect dependency logic).
- **Negative Optimization (allDevices)**: Verifies that items are NOT requested from Zabbix if neither `items` nor `state` (or state sub-properties) are requested within the `allDevices` query.
- **allDevices deviceType filter**: Verifies that the `allDevices` query only returns hosts that have a `deviceType` tag, and that the `deviceType` field is populated for all results.
- **pushHistory mutation**: Verifies that the `pushHistory` mutation correctly pushes data to ZABBIX_TRAP items, using either item ID or a combination of host and item key.
## ✅ Test Coverage Checklist
| ID | Test Case | Category | Technology | Code Link |
|:---|:---|:---|:---|:---|
| TC-HOST-01 | Query allHosts using sample | Integration | Jest | [src/test/host_integration.test.ts](../src/test/host_integration.test.ts) |
| TC-HOST-02 | Import hosts using sample | Integration | Jest | [src/test/host_integration.test.ts](../src/test/host_integration.test.ts) |
| TC-HOST-03 | importHostGroups - create new hierarchy | Unit | Jest | [src/test/host_importer.test.ts](../src/test/host_importer.test.ts) |
| TC-HOST-04 | importHosts - basic host | Unit | Jest | [src/test/host_importer.test.ts](../src/test/host_importer.test.ts) |
| TC-HOST-05 | allHosts query | Unit | Jest | [src/test/host_query.test.ts](../src/test/host_query.test.ts) |
| TC-HOST-06 | allDevices query | Unit | Jest | [src/test/host_query.test.ts](../src/test/host_query.test.ts) |
| TC-HOST-07 | allHostGroups query | Unit | Jest | [src/test/host_query.test.ts](../src/test/host_query.test.ts) |
| TC-HOST-08 | allHostGroups query - default pattern | Unit | Jest | [src/test/host_query.test.ts](../src/test/host_query.test.ts) |
| TC-HOST-09 | locations query | Unit | Jest | [src/test/host_query.test.ts](../src/test/host_query.test.ts) |
| TC-TEMP-01 | Import templates using sample | Integration | Jest | [src/test/template_integration.test.ts](../src/test/template_integration.test.ts) |
| TC-TEMP-02 | Import and Export templates comparison | Integration | Jest | [src/test/template_integration.test.ts](../src/test/template_integration.test.ts) |
| TC-TEMP-03 | Import and Export template groups comparison | Integration | Jest | [src/test/template_integration.test.ts](../src/test/template_integration.test.ts) |
| TC-TEMP-04 | templates query - returns all | Unit | Jest | [src/test/template_query.test.ts](../src/test/template_query.test.ts) |
| TC-TEMP-05 | templates query - filters by hostids | Unit | Jest | [src/test/template_query.test.ts](../src/test/template_query.test.ts) |
| TC-TEMP-06 | templates query - filters by name_pattern | Unit | Jest | [src/test/template_query.test.ts](../src/test/template_query.test.ts) |
| TC-TEMP-07 | templates query - name_pattern wildcard | Unit | Jest | [src/test/template_query.test.ts](../src/test/template_query.test.ts) |
| TC-TEMP-08 | importTemplateGroups - create new | Unit | Jest | [src/test/template_importer.test.ts](../src/test/template_importer.test.ts) |
| TC-TEMP-09 | importTemplateGroups - group exists | Unit | Jest | [src/test/template_importer.test.ts](../src/test/template_importer.test.ts) |
| TC-TEMP-10 | importTemplates - basic template | Unit | Jest | [src/test/template_importer.test.ts](../src/test/template_importer.test.ts) |
| TC-TEMP-11 | importTemplates - complex template | Unit | Jest | [src/test/template_importer.test.ts](../src/test/template_importer.test.ts) |
| TC-TEMP-12 | importTemplates - template query | Unit | Jest | [src/test/template_importer.test.ts](../src/test/template_importer.test.ts) |
| TC-TEMP-13 | importTemplates - error data field | Unit | Jest | [src/test/template_importer.test.ts](../src/test/template_importer.test.ts) |
| TC-TEMP-14 | deleteTemplates - success | Unit | Jest | [src/test/template_deleter.test.ts](../src/test/template_deleter.test.ts) |
| TC-TEMP-15 | deleteTemplates - error | Unit | Jest | [src/test/template_deleter.test.ts](../src/test/template_deleter.test.ts) |
| TC-TEMP-16 | deleteTemplates - by name_pattern | Unit | Jest | [src/test/template_deleter.test.ts](../src/test/template_deleter.test.ts) |
| TC-TEMP-17 | deleteTemplates - merged IDs | Unit | Jest | [src/test/template_deleter.test.ts](../src/test/template_deleter.test.ts) |
| TC-TEMP-18 | deleteTemplateGroups - success | Unit | Jest | [src/test/template_deleter.test.ts](../src/test/template_deleter.test.ts) |
| TC-TEMP-19 | deleteTemplateGroups - error | Unit | Jest | [src/test/template_deleter.test.ts](../src/test/template_deleter.test.ts) |
| TC-TEMP-20 | deleteTemplateGroups - by name_pattern | Unit | Jest | [src/test/template_deleter.test.ts](../src/test/template_deleter.test.ts) |
| TC-AUTH-01 | exportUserRights query | Unit | Jest | [src/test/user_rights.test.ts](../src/test/user_rights.test.ts) |
| TC-AUTH-02 | userPermissions query | Unit | Jest | [src/test/user_rights.test.ts](../src/test/user_rights.test.ts) |
| TC-AUTH-03 | hasPermissions query | Unit | Jest | [src/test/user_rights.test.ts](../src/test/user_rights.test.ts) |
| TC-AUTH-04 | importUserRights mutation | Unit | Jest | [src/test/user_rights.test.ts](../src/test/user_rights.test.ts) |
| TC-AUTH-05 | Import user rights using sample | Integration | Jest | [src/test/user_rights_integration.test.ts](../src/test/user_rights_integration.test.ts) |
| TC-OPT-01 | Verify Query Optimization (reduced output) | Unit/E2E | Jest/Regression | [src/test/query_optimization.test.ts](../src/test/query_optimization.test.ts) |
| TC-OPT-02 | Verify skippable parameters | Unit/E2E | Jest/Regression | [src/test/query_optimization.test.ts](../src/test/query_optimization.test.ts) |
| TC-OPT-03 | Verify indirect dependencies | Unit | Jest | [src/test/indirect_dependencies.test.ts](../src/test/indirect_dependencies.test.ts) |
| TC-CONF-01 | schema_loader uses Config variables | Unit | Jest | [src/test/schema_config.test.ts](../src/test/schema_config.test.ts) |
| TC-CONF-02 | constants are derived from Config | Unit | Jest | [src/test/zabbix_api_config.test.ts](../src/test/zabbix_api_config.test.ts) |
| TC-CONF-03 | logger levels initialized from Config | Unit | Jest | [src/test/logger_config.test.ts](../src/test/logger_config.test.ts) |
| TC-CONF-04 | apiVersion query | Unit | Jest | [src/test/misc_resolvers.test.ts](../src/test/misc_resolvers.test.ts) |
| TC-CONF-05 | login query | Unit | Jest | [src/test/misc_resolvers.test.ts](../src/test/misc_resolvers.test.ts) |
| TC-CONF-06 | logout query | Unit | Jest | [src/test/misc_resolvers.test.ts](../src/test/misc_resolvers.test.ts) |
| TC-CONF-07 | Parse Zabbix Args | Unit | Jest | [src/test/zabbix_api_args_parser.test.ts](../src/test/zabbix_api_args_parser.test.ts) |
| TC-DOCS-01 | Zabbix Docs Samples Integration | Integration | Jest | [src/test/zabbix_docs_samples.test.ts](../src/test/zabbix_docs_samples.test.ts) |
| TC-MCP-01 | MCP Operations Validation | Integration | Jest | [src/test/mcp_operations_validation.test.ts](../src/test/mcp_operations_validation.test.ts) |
| TC-SCHEMA-01 | DistanceTrackerDevice Query | Integration | Jest | [src/test/schema_dependent_queries.test.ts](../src/test/schema_dependent_queries.test.ts) |
| TC-E2E-01 | Run complete smoketest | E2E | GraphQL / MCP | [mcp/operations/runSmoketest.graphql](../mcp/operations/runSmoketest.graphql) |
| TC-E2E-02 | Run all regression tests | E2E | GraphQL / MCP | [mcp/operations/runAllRegressionTests.graphql](../mcp/operations/runAllRegressionTests.graphql) |
## 📝 Test Case Obligations
As per project guidelines, every new feature or bug fix must be accompanied by a described test case in this specification.
- **Feature**: A new feature must have a corresponding test case (TC) defined before implementation.
- **Bug Fix**: A bug fix must include a reproduction test case that fails without the fix and passes with it. Additionally, a permanent regression test must be added to the automated suite (e.g., `RegressionTestExecutor`) to prevent the issue from re-occurring.
- **Documentation**: The `docs/tests.md` file must be updated to reflect any changes in test coverage.
- **Categorization**: Tests must be categorized as Unit, Integration, or End-to-End (E2E).
Update any bookmarks or references accordingly.