Skip to content

Commit 5cc6e2e

Browse files
committed
Merge remote-tracking branch 'origin/main' into persist
2 parents 1870de1 + 8e7e8d2 commit 5cc6e2e

File tree

12 files changed

+330
-231
lines changed

12 files changed

+330
-231
lines changed

dbquery/pings/postgresql/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Ping PostgreSQL
2+
3+
Simple schema that when deployed provides an easy way to check that a
4+
PostgreSQL database can be connected to from a GraphQL endpoint.
5+
6+
## Setup
7+
8+
Either set an environment variable or an `.env` file containing the URI of the PostgreSQL instance.
9+
10+
Replace `<<xxx>>` values with the correct connection information.
11+
12+
If a port number is required then add it to the host as `:1234`.
13+
14+
If the password contains special characters then must be URL escaped.
15+
16+
### Environment variable
17+
```
18+
export STEPZEN_PG_DB_URI=postgresql://<<host>>/<<database>>?user=<<user>>&password=<<password>>
19+
```
20+
21+
### `.env` contents
22+
23+
```
24+
STEPZEN_PG_DB_URI=postgresql://<<host>>/<<database>>?user=<<user>>&password=<<password>>
25+
```
26+
27+
## Deploy
28+
29+
```
30+
stepzen deploy
31+
```
32+
33+
## Test
34+
35+
```
36+
stepzen request '{ping{status}}'
37+
```
38+
39+
## Example
40+
41+
```
42+
>stepzen deploy
43+
Deploying dbping/postgresql to StepZen... done in 443ms 🚀
44+
✓ 🔐 https://danville.us-east-a.ibm.stepzen.net/dbping/postgresql/__graphql
45+
✓ 🔐 wss://danville.us-east-a.ibm.stepzen.net/stepzen-subscriptions/dbping/postgresql/__graphql (subscriptions)
46+
47+
You can test your hosted API with curl:
48+
49+
curl https://danville.us-east-a.ibm.stepzen.net/dbping/postgresql/__graphql \
50+
--header "Authorization: Apikey $(stepzen whoami --apikey)" \
51+
--header "Content-Type: application/json" \
52+
--data-raw '{
53+
"query": "query SampleQuery { __schema { description queryType { fields {name} } } }"
54+
}'
55+
56+
stepzen request '{ping{status}}'
57+
{
58+
"data": {
59+
"ping": {
60+
"status": "ok"
61+
}
62+
}
63+
}
64+
```
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
configurationset:
2+
- configuration:
3+
name: pgdb
4+
uri: STEPZEN_PG_DB_URI
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
type Query {
2+
"""
3+
Pings the configured database by running a SQL statement
4+
that does not access any user tables or schema.
5+
"""
6+
ping: Ping
7+
@dbquery(
8+
type: "postgresql"
9+
query: "SELECT 'ok' AS status"
10+
configuration: "pgdb"
11+
)
12+
}
13+
type Ping {
14+
status: String
15+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"endpoint": "dbping/postgresql"
3+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const {
2+
deployAndRun,
3+
authTypes,
4+
getTestDescription,
5+
} = require("../../../../tests/gqltest.js");
6+
7+
testDescription = getTestDescription("snippets", __dirname);
8+
9+
describe(testDescription, function () {
10+
const tests = [];
11+
return deployAndRun(__dirname, tests);
12+
});
Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
type Customer {
2-
name: String
3-
city: String
2+
name: String
3+
city: String
44
}
55
type Query {
6-
# An ecmascript generator of customer data.
7-
# Of course, in real life you will call an API or a database. You can do that by changing the `endpoint` argument on the `@rest` directive.
8-
# https://stepzen.com/docs/connecting-backends/how-to-connect-a-rest-service
9-
customer (id: ID): Customer
10-
@rest (endpoint: "stepzen:empty"
11-
ecmascript: """
12-
function transformREST(s) {
13-
var id = get('id')
14-
if (id==1)
15-
return (JSON.stringify({"name":"John Doe","city":"Miami"}))
16-
else
17-
return (JSON.stringify({"name":"Jane Smith","city":"Santa Clara"}))
18-
}
19-
"""
6+
# An ecmascript generator of customer data.
7+
# Of course, in real life you will call an API or a database. You can do that by changing the `endpoint` argument on the `@rest` directive.
8+
# https://stepzen.com/docs/connecting-backends/how-to-connect-a-rest-service
9+
customer(id: ID!): Customer
10+
@rest(
11+
endpoint: "stepzen:empty"
12+
ecmascript: """
13+
function transformREST(s) {
14+
var id = get('id')
15+
if (id==1)
16+
return (JSON.stringify({"name":"John Doe","city":"Miami"}))
17+
else
18+
return (JSON.stringify({"name":"Jane Smith","city":"Santa Clara"}))
19+
}
20+
"""
2021
)
21-
}
22+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
query Customer($id: ID!) {
2+
customer(id: $id) {
3+
name
4+
city
5+
}
6+
}
Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const fs = require("fs");
2+
const path = require("node:path");
13
const {
24
deployAndRun,
35
authTypes,
@@ -6,8 +8,42 @@ const {
68

79
testDescription = getTestDescription("snippets", __dirname);
810

11+
const requestsFile = path.join(path.dirname(__dirname), "operations.graphql");
12+
const requests = fs.readFileSync(requestsFile, "utf8").toString();
13+
914
describe(testDescription, function () {
15+
// note tests using no authorization since api is public
1016
const tests = [
11-
]
17+
{
18+
label: "customer-1",
19+
query: requests,
20+
operationName: "Customer",
21+
variables: {
22+
id: 1,
23+
},
24+
expected: {
25+
customer: {
26+
name: "John Doe",
27+
city: "Miami",
28+
},
29+
},
30+
authType: authTypes.noAuth,
31+
},
32+
{
33+
label: "customer-2",
34+
query: requests,
35+
operationName: "Customer",
36+
variables: {
37+
id: 2,
38+
},
39+
expected: {
40+
customer: {
41+
name: "Jane Smith",
42+
city: "Santa Clara",
43+
},
44+
},
45+
authType: authTypes.noAuth,
46+
},
47+
];
1248
return deployAndRun(__dirname, tests);
13-
});
49+
});

tests/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Must have one environment variable set:
88

99
* `STEPZEN_ENDPOINT` - StepZen endpoint all the tests will be deployed to (one at a time). For example:
1010
```
11-
export STEPZEN_ENDPOINT=https://YOUR_ACCOUNT.stepzen.net/test/snippets/graphql
11+
export STEPZEN_ENDPOINT=https://YOUR_ACCOUNT.stepzen.net/test/snippets/__graphql
1212
```
1313

1414
You can also set this environment variable in a `.env` file in the `tests` folder. By copying the `.env.example` file.

tests/gqltest.js

Lines changed: 38 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
require("dotenv").config();
2-
const fetch = require("node-fetch");
3-
const { expect } = require("chai");
42
const { execSync } = require("child_process");
53
const { URL } = require("url");
64
const path = require("node:path");
75

6+
const {
7+
GQLHeaders,
8+
executeOK,
9+
logOnFail,
10+
} = require('gqltest/packages/gqltest/gqltest.js')
11+
812
const authTypes = {
913
adminKey: 1,
1014
apiKey: 2,
@@ -15,10 +19,8 @@ Object.freeze(authTypes);
1519

1620
// We use admin key to test because there is a cache optimization for apikey's that is not conducive
1721
// to rapid deploy and run cycles that occur with this type of testing
18-
const adminKey =
19-
`apikey ` + execSync(`stepzen whoami --adminkey`).toString().trim();
20-
const apiKey =
21-
`apikey ` + execSync(`stepzen whoami --apikey`).toString().trim();
22+
const adminKey = execSync(`stepzen whoami --adminkey`).toString().trim();
23+
const apiKey = execSync(`stepzen whoami --apikey`).toString().trim();
2224

2325
const endpoint = process.env.STEPZEN_ENDPOINT;
2426

@@ -45,50 +47,27 @@ function deployEndpoint(endpoint, dirname) {
4547
// as a test returning the response.
4648
// The test will fail if the request does not
4749
// have status 200 or has any GraphQL errors.
48-
function runGqlOk(authType, endpoint, documentId, query, variables, operationName) {
50+
async function runGqlOk(authType, endpoint, request, expected) {
51+
let headers = new GQLHeaders();
4952
switch (authType) {
5053
case authTypes.adminKey:
51-
authValue = adminKey;
54+
headers.withAPIKey(adminKey);
5255
break;
5356
case authTypes.apiKey:
54-
authValue = apiKey;
57+
headers.withAPIKey(apiKey);
5558
break;
56-
// Have not implemented jwt and noAuth yet
59+
// Have not implemented jwt yet
5760
case authTypes.jwt:
5861
case authTypes.noAuth:
5962
default:
60-
authValue = "";
6163
}
62-
return fetch(endpoint, {
63-
method: "POST",
64-
headers: {
65-
"Content-Type": "application/json",
66-
Authorization: authValue,
67-
},
68-
body: JSON.stringify({
69-
documentId: documentId,
70-
query: query,
71-
variables: variables,
72-
operationName: operationName,
73-
}),
64+
await executeOK({
65+
test: this,
66+
endpoint,
67+
headers,
68+
request,
69+
expected,
7470
})
75-
.then(function (result) {
76-
expect(result.status).to.equal(200);
77-
return result;
78-
})
79-
.then(function (result) {
80-
return result.json();
81-
})
82-
.then(function (response) {
83-
expect(response.errors, `no errors should exist: ${JSON.stringify(response.errors)}`).to.be.undefined;
84-
return response;
85-
});
86-
}
87-
88-
// tests that the data key in a GraphQL response
89-
// is equal to value.
90-
function expectData(response, value) {
91-
expect(response.data).to.eql(value);
9271
}
9372

9473
// deploys graphql schema located in dirname to the test endpoint provided by the environment (process.env.STEPZEN_ENDPOINT),
@@ -102,20 +81,30 @@ function deployAndRun(dirname, tests) {
10281
return deployEndpoint(endpoint, dirname);
10382
});
10483

84+
afterEach('log-failure', logOnFail)
10585
tests.forEach(
10686
({ label, documentId, query, variables, operationName, expected, authType }) => {
107-
it(label, function () {
87+
it(label, async function () {
10888
this.timeout(4000); // Occasional requests take > 2s
109-
return runGqlOk(
89+
let request = {}
90+
if (query) {
91+
request.query = query;
92+
}
93+
if (documentId) {
94+
request.documentId = documentId;
95+
}
96+
if (operationName) {
97+
request.operationName = operationName;
98+
}
99+
if (variables) {
100+
request.variables = variables;
101+
}
102+
return await runGqlOk(
110103
authType,
111104
endpoint,
112-
documentId,
113-
query,
114-
variables,
115-
operationName
116-
).then(function (response) {
117-
expectData(response, expected);
118-
});
105+
request,
106+
expected,
107+
);
119108
});
120109
}
121110
);
@@ -129,8 +118,6 @@ function getTestDescription(testRoot, fullDirName) {
129118
return segments.slice(rootIndex + 1, -1).join("/");
130119
}
131120

132-
exports.runGqlOk = runGqlOk;
133-
exports.expectData = expectData;
134121
exports.deployAndRun = deployAndRun;
135122
exports.authTypes = authTypes;
136123
exports.getTestDescription = getTestDescription;

0 commit comments

Comments
 (0)