API test suite for the Open-Meteo API — free, no authentication required, real climate data.
| Tool | Version | Role |
|---|---|---|
| TypeScript | ^5.4 | Static typing |
| Jest | ^29.7 | Test runner + assertions |
| ts-jest | ^29.1 | TypeScript compilation in Jest |
| Axios | ^1.6 | HTTP client |
tests-api/
├── src/
│ ├── helpers/
│ │ └── client.ts # Axios instance + shared constants
│ └── forecast.test.ts # Test suite for /forecast endpoint
├── postman/
│ └── open-meteo-collection.json # Postman collection (importable)
├── .github/
│ └── workflows/
│ └── api-tests.yml # CI/CD — runs on every push
├── jest.config.js
├── tsconfig.json
└── package.json
Status & Availability
- ✅ Status 200 for a valid request
- ✅ Response time under 5 seconds
- ✅ Content-Type
application/json
Schema Validation
- ✅ Top-level fields:
latitude,longitude,timezone,elevation - ✅
hourly.timeandhourly.temperature_2marrays present and equal length - ✅
daily.precipitation_sumarray present - ✅ Daily forecast returns 7 days by default
Data Integrity
- ✅ Returned coordinates close to requested (< 1 degree)
- ✅ Temperatures within realistic range (−80°C to 60°C)
- ✅ Precipitation values are non-negative
Multi-location — using it.each
- ✅ São Paulo, London, Tokyo
Error Handling
- ✅ Status 400 for invalid coordinates (
latitude=999&longitude=999) - ✅ Error body contains
reasonfield - ✅ Status 200 with no params — API uses default coordinates (documented behaviour)
jest.config.js instead of jest.config.ts — Jest requires ts-node to parse a TypeScript config file. The /** @type {import('jest').Config} */ comment preserves IntelliSense in VS Code with no extra dependencies.
Axios over native fetch — Node 20's native fetch does not throw on 4xx/5xx responses. Axios throws automatically, which simplifies error handling in tests. It also allows global baseURL, timeout and headers configuration via axios.create() in client.ts, avoiding repetition across test files.
validateStatus: () => true for error testing — the try/catch pattern only works if Axios throws an exception. If the API returns 200 or the request fails without a response object, err.response is undefined and the test crashes with a property read error instead of a clean assertion failure. validateStatus: () => true tells Axios never to throw regardless of status, so the assertion is made directly on the response — more robust and more readable.
Documented real API behaviour — during development, the suite assumed Open-Meteo would return 400 for a request with no parameters. Testing revealed it returns 200, using default coordinates instead. Rather than forcing the test to pass with a wrong expectation, the premise was corrected and the real behaviour was documented.
describe blocks by concern — tests are organised into four groups: Status & availability, Schema validation, Data integrity and Error handling.
it.each for multi-location — instead of duplicating three identical tests for São Paulo, London and Tokyo, it.each parametrises the same case with different data, generating descriptive test names automatically.
testTimeout: 15000 — Jest's default timeout is 5 seconds, but 15 seconds avoids false negatives on slow connections without masking real latency issues.
A Postman collection mirroring all Jest scenarios is available at postman/open-meteo-collection.json.
To import: open Postman → Import → select the file. All collection variables (baseUrl, coordinates) are pre-configured.
To run all tests: right-click the collection → Run collection → Run Open-Meteo API Tests.
The collection covers the same five groups as the Jest suite. Scripts are written using Postman's built-in pm library.
npm install
npm test # run all tests
npm run test:coverage # run with coverage report
npm run test:watch # interactive watch modeAfter running npm run test:coverage, the HTML report is available at ./coverage/index.html.
The GitHub Actions workflow runs automatically on every push to main or develop and on pull requests to main. The coverage report is uploaded as an artifact after each run.