Skip to content

Commit

Permalink
Merge pull request #56 from olisaagbafor/test/karate-setup
Browse files Browse the repository at this point in the history
Test/karate setup
  • Loading branch information
zleypner authored Dec 12, 2024
2 parents 53f6cae + 400c655 commit 679fe14
Show file tree
Hide file tree
Showing 12 changed files with 322 additions and 15 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,7 @@ bower_components/
# Test output
test-output/
*.tap

# Karate reports
tests/target/
tests/results/
14 changes: 14 additions & 0 deletions Dockerfile.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM openjdk:17

WORKDIR /app

# Copy test files
COPY tests /app/tests

# Make sure karate-config.js is in the right place
RUN mkdir -p /app/tests/karate/src/test/resources
# Create directory for test results
RUN mkdir -p /app/target/karate-reports

# Set default command
CMD ["java", "-jar", "/app/tests/karate.jar", "--configdir", "/app/tests/karate/src/test/resources", "/app/tests/karate/features"]
103 changes: 90 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Ensures funds are automatically released based on the terms of the agreement, wi

0. Install Docker and Docker Compose
1. Download the Hasura global binary. See steps [here](https://hasura.io/docs/2.0/hasura-cli/install-hasura-cli/)
2. Run
2. Run

```shell

Expand Down Expand Up @@ -84,28 +84,105 @@ hasura migrate apply --admin-secret myadminsecretkey

If you wanna use the hasura web console and access it on `http://localhost:9695/`:


```shell
hasura console --admin-secret myadminsecretkey
```

And you should be good to go to start and work on this.


## 📋 **Known Issues**

### 📝 **Title**
### 📝 **Title**

**Error Running Docker Compose**

### **Error Message**
### **Error Message**

> `Rosetta error: Rosetta is only intended to run on Apple Silicon with a macOS host using Virtualization.framework with Rosetta mode enabled`
### 🔍 **Error Description**
1. Run `docker compose up -d`.
2. If the **Backend postgres-1 module** can't start and shows the error above:
- This is due to an issue with Rosetta settings on Apple Silicon devices.
3.**Solution:**
### 🔍 **Error Description**

1. Run `docker compose up -d`.
2. If the **Backend postgres-1 module** can't start and shows the error above:
- This is due to an issue with Rosetta settings on Apple Silicon devices.
3.**Solution:**
- Go to **Docker Settings** and disable the:
`Use Rosetta for x86_64/amd64 emulation on Apple Silicon` selection button.
- 🔄 Restart Docker.
- 🚀 It should now run great!
`Use Rosetta for x86_64/amd64 emulation on Apple Silicon` selection button.
- 🔄 Restart Docker.
- 🚀 It should now run great!

# Backend Tests

This project uses Karate framework for API testing. The tests are designed to run in a Docker environment.

## Prerequisites

- Docker
- Docker Compose

## Project Structure

```
backend/
├── docker-compose-test.yml
├── Dockerfile.test
└── tests/
├── karate.jar
└── karate/
├── features/
│ ├── auth/
│ │ ├── login.feature
│ │ └── permissions.feature
│ └── users/
│ ├── create.feature
│ └── query.feature
└── src/
└── test/
└── resources/
└── karate-config.js
```

## Running Tests

To run all tests:

```bash
docker compose -f docker-compose-test.yml up --build --abort-on-container-exit
```

This command will:

1. Build the test container
2. Start PostgreSQL and Hasura containers
3. Run all Karate tests
4. Show test results in the console
5. Generate HTML reports in `target/karate-reports/`

## Test Reports

After running the tests, you can find the HTML reports at:

- Summary: `tests/results/karate-summary.html`
- Detailed: `tests/results/karate-tags.html`

## Development

### Adding New Tests

1. Create new `.feature` files in `tests/karate/features/`
2. Follow the Karate DSL syntax
3. Tests will be automatically picked up when running the test command

### Configuration

- Main config: `tests/karate/src/test/resources/karate-config.js`
- Database config: `docker-compose-test.yml`
- Test environment: `Dockerfile.test`

## Troubleshooting

If tests fail with connection errors:

1. Ensure all containers are running: `docker compose -f docker-compose-test.yml ps`
2. Check container logs: `docker compose -f docker-compose-test.yml logs`
3. Verify network connectivity: `docker network inspect backend_test-network`
53 changes: 53 additions & 0 deletions docker-compose-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
services:
postgres_test:
image: postgres:15
restart: always
environment:
POSTGRES_PASSWORD: postgrespassword
ports:
- "5432:5432"
networks:
- test-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5

graphql-engine-test:
image: hasura/graphql-engine:latest
ports:
- "8081:8080"
depends_on:
postgres_test:
condition: service_healthy
environment:
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres_test:5432/postgres
HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
HASURA_GRAPHQL_DEV_MODE: "true"
HASURA_GRAPHQL_ADMIN_SECRET: myadminsecretkey
HASURA_GRAPHQL_JWT_SECRET: '{"type":"HS256", "key": "12345678901234567890123456789012", "claims_format": "json", "claims_namespace": "https://hasura.io/jwt/claims"}'
HASURA_GRAPHQL_UNAUTHORIZED_ROLE: "anonymous"
HASURA_GRAPHQL_LOG_LEVEL: "debug"
HASURA_GRAPHQL_ENABLED_LOG_TYPES: "startup,http-log,webhook-log,websocket-log,query-log"
ACTION_BASE_URL: http://action-handler:3000
volumes:
- ./tests/metadata:/hasura-metadata
networks:
- test-network

karate:
build:
context: .
dockerfile: Dockerfile.test
volumes:
- ./tests/results:/app/target/karate-reports
depends_on:
graphql-engine-test:
condition: service_started
networks:
- test-network

networks:
test-network:
driver: bridge
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "**SafeTrust** is a decentralized platform designed to revolutionize P2P transactions, providing secure deposits and payments powered by blockchain and trustless technologies. 🌐✨ Experience transparency and reliability in every cryptocurrency transaction. 💸🔒",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "java -jar /app/tests/karate.jar /app/tests/karate/features"
},
"repository": {
"type": "git",
Expand All @@ -23,6 +23,7 @@
"express-rate-limit": "^7.4.1",
"graphql-request": "^7.1.2",
"nodemailer": "^6.9.16",
"winston": "^3.17.0"
"winston": "^3.17.0",
"cucumber-html-reporter": "^5.5.0"
}
}
Binary file added tests/karate.jar
Binary file not shown.
28 changes: 28 additions & 0 deletions tests/karate/features/auth/login.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
Feature: User Authentication

Background:
* print '=== Loading feature file ==='
* url baseUrl
* print 'URL set to:', baseUrl
* header x-hasura-admin-secret = adminSecret

Scenario: Check test database connection
* print 'Starting database check'
Given path '/'
And def query =
"""
{
"query": "query { __type(name: \"User\") { fields { name type { name kind } } } }"
}
"""
And request query
When method POST
Then status 200
* print 'Schema:', response.data

Scenario: Check test environment health
* print 'Starting health check'
Given url baseUrl.replace('/v1/graphql', '/healthz')
When method GET
Then status 200
* print 'Health response:', response
16 changes: 16 additions & 0 deletions tests/karate/features/auth/permissions.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Feature: Authorization Permissions

Background:
* url baseUrl
* print '=== Loading feature file ==='
* print 'URL set to:', baseUrl

Scenario: User can access their own data
* def token = tokenHelper({ uid: 'test-user', role: 'user' })
* header Authorization = token
* header x-hasura-admin-secret = adminSecret

Given path '/'
And request { query: "{ __type(name: \"User\") { fields { name } } }" }
When method POST
Then status 200
14 changes: 14 additions & 0 deletions tests/karate/features/users/create.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Feature: Create User

Background:
* url baseUrl
* print '=== Loading feature file ==='
* print 'URL set to:', baseUrl

Scenario: Check Hasura health
Given path ''
And header x-hasura-admin-secret = adminSecret
And request { query: "query { __typename }" }
When method POST
Then status 200
And match response == { data: { __typename: 'query_root' } }
19 changes: 19 additions & 0 deletions tests/karate/features/users/query.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Feature: Query Users

Background:
* url baseUrl
* print '=== Loading feature file ==='
* print 'URL set to:', baseUrl
* header x-hasura-admin-secret = adminSecret

Scenario: Query existing user
Given request { query: "{ __typename }" }
When method POST
Then status 200
And match response == { data: { __typename: 'query_root' } }

Scenario: Query non-existing user
Given request { query: "{ __typename }" }
When method POST
Then status 200
And match response == { data: { __typename: 'query_root' } }
31 changes: 31 additions & 0 deletions tests/karate/features/users/wallets.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Feature: User Wallets

Background:
* url baseUrl
* print '=== Loading feature file ==='
* print 'URL set to:', baseUrl

Scenario: Get schema information
Given header Authorization = tokenHelper({ role: 'admin' })
And header x-hasura-admin-secret = adminSecret
And request
"""
{
"query": "
query IntrospectionQuery {
__schema {
queryType {
fields {
name
description
}
}
}
}
"
}
"""
When method POST
Then status 200
And match response.errors == '#notpresent'
* print 'Available queries:', response.data.__schema.queryType.fields
50 changes: 50 additions & 0 deletions tests/karate/src/test/resources/karate-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
function fn() {
karate.log("=== Starting karate-config.js ===");

// Configure pretty logging
karate.configure("logPrettyRequest", true);
karate.configure("logPrettyResponse", true);

// Basic configuration
var config = {
baseUrl: "http://graphql-engine-test:8080/v1/graphql",
adminSecret: "myadminsecretkey",
};

// Token helper function
config.tokenHelper = function (claims) {
var Base64 = Java.type("java.util.Base64");
var defaultClaims = {
"https://hasura.io/jwt/claims": {
"x-hasura-allowed-roles": ["user"],
"x-hasura-default-role": "user",
"x-hasura-user-id": "00000000-0000-0000-0000-000000000000",
},
};

if (claims && claims.role === "admin") {
defaultClaims["https://hasura.io/jwt/claims"] = {
"x-hasura-allowed-roles": ["user", "admin"],
"x-hasura-default-role": "admin",
"x-hasura-user-id": "admin-user",
};
}

var header = { alg: "HS256", typ: "JWT" };

// Properly encode each part
var headerBase64 = Base64.getUrlEncoder().withoutPadding().encodeToString(JSON.stringify(header).getBytes("UTF-8"));
var payloadBase64 = Base64.getUrlEncoder().withoutPadding().encodeToString(JSON.stringify(defaultClaims).getBytes("UTF-8"));

return "Bearer " + headerBase64 + "." + payloadBase64 + ".your-secret-key";
};

// Set default headers
config.headers = {
"Content-Type": "application/json",
"X-Hasura-Admin-Secret": config.adminSecret,
};

karate.log("Config initialized:", config);
return config;
}

0 comments on commit 679fe14

Please sign in to comment.