@teamkeel/testing-runtime 0.365.15-prerelease2 → 0.365.15-prerelease21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/ActionExecutor.mjs +5 -80
- package/src/Executor.mjs +111 -0
- package/src/JobExecutor.mjs +5 -89
- package/src/SubscriberExecutor.mjs +10 -0
- package/src/index.mjs +1 -0
- package/src/toHaveAuthorizationError.mjs +5 -2
package/package.json
CHANGED
package/src/ActionExecutor.mjs
CHANGED
|
@@ -1,85 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Executor } from "./Executor.mjs";
|
|
2
2
|
|
|
3
|
-
export class ActionExecutor {
|
|
3
|
+
export class ActionExecutor extends Executor {
|
|
4
4
|
constructor(props) {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
props.apiBaseUrl = process.env.KEEL_TESTING_ACTIONS_API_URL;
|
|
6
|
+
props.parseJsonResult = true;
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
// _execute method for any unknown properties. This creates
|
|
10
|
-
// the actions API we want but in a dynamic way without needing
|
|
11
|
-
// codegen. We then generate the right type definitions for
|
|
12
|
-
// this class in the @teamkeel/testing package.
|
|
13
|
-
return new Proxy(this, {
|
|
14
|
-
get(target, prop) {
|
|
15
|
-
const v = Reflect.get(...arguments);
|
|
16
|
-
if (v !== undefined) {
|
|
17
|
-
return v;
|
|
18
|
-
}
|
|
19
|
-
return target._execute.bind(target, prop);
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
withIdentity(i) {
|
|
24
|
-
return new ActionExecutor({ identity: i });
|
|
25
|
-
}
|
|
26
|
-
withAuthToken(t) {
|
|
27
|
-
return new ActionExecutor({ authToken: t });
|
|
28
|
-
}
|
|
29
|
-
_execute(method, params) {
|
|
30
|
-
const headers = { "Content-Type": "application/json" };
|
|
31
|
-
|
|
32
|
-
// An Identity instance is provided make a JWT
|
|
33
|
-
if (this._identity !== null) {
|
|
34
|
-
headers["Authorization"] =
|
|
35
|
-
"Bearer " +
|
|
36
|
-
jwt.sign(
|
|
37
|
-
{},
|
|
38
|
-
// Not using a signing algorithm, therefore the private key is undefined
|
|
39
|
-
undefined,
|
|
40
|
-
{
|
|
41
|
-
algorithm: "none",
|
|
42
|
-
expiresIn: 60 * 60 * 24,
|
|
43
|
-
subject: this._identity.id,
|
|
44
|
-
issuer: "keel",
|
|
45
|
-
}
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// If an auth token is provided that can be sent as-is
|
|
50
|
-
if (this._authToken !== null) {
|
|
51
|
-
headers["Authorization"] = "Bearer " + this._authToken;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Use the HTTP JSON API as that returns more friendly errors than
|
|
55
|
-
// the JSON-RPC API.
|
|
56
|
-
return fetch(process.env.KEEL_TESTING_ACTIONS_API_URL + "/" + method, {
|
|
57
|
-
method: "POST",
|
|
58
|
-
body: JSON.stringify(params),
|
|
59
|
-
headers,
|
|
60
|
-
}).then((r) => {
|
|
61
|
-
if (r.status !== 200) {
|
|
62
|
-
// For non-200 first read the response as text
|
|
63
|
-
return r.text().then((t) => {
|
|
64
|
-
let d;
|
|
65
|
-
try {
|
|
66
|
-
d = JSON.parse(t);
|
|
67
|
-
} catch (e) {
|
|
68
|
-
// If JSON parsing fails then throw an error with the
|
|
69
|
-
// response text as the message
|
|
70
|
-
throw new Error(t);
|
|
71
|
-
}
|
|
72
|
-
// Otherwise throw the parsed JSON error response
|
|
73
|
-
// We override toString as otherwise you get expect errors like:
|
|
74
|
-
// `expected to resolve but rejected with "[object Object]"`
|
|
75
|
-
Object.defineProperty(d, "toString", {
|
|
76
|
-
value: () => t,
|
|
77
|
-
enumerable: false,
|
|
78
|
-
});
|
|
79
|
-
throw d;
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
return r.json();
|
|
83
|
-
});
|
|
8
|
+
super(props);
|
|
84
9
|
}
|
|
85
10
|
}
|
package/src/Executor.mjs
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import jwt from "jsonwebtoken";
|
|
2
|
+
|
|
3
|
+
export class Executor {
|
|
4
|
+
constructor(props) {
|
|
5
|
+
this._identity = props.identity || null;
|
|
6
|
+
this._authToken = props.authToken || null;
|
|
7
|
+
this._apiBaseUrl = props.apiBaseUrl;
|
|
8
|
+
this._parseJsonResult = props.parseJsonResult;
|
|
9
|
+
|
|
10
|
+
// Return a proxy which will return a bound version of the
|
|
11
|
+
// _execute method for any unknown properties. This creates
|
|
12
|
+
// the actions API we want but in a dynamic way without needing
|
|
13
|
+
// codegen. We then generate the right type definitions for
|
|
14
|
+
// this class in the @teamkeel/testing package.
|
|
15
|
+
return new Proxy(this, {
|
|
16
|
+
get(target, prop) {
|
|
17
|
+
const v = Reflect.get(...arguments);
|
|
18
|
+
if (v !== undefined) {
|
|
19
|
+
return v;
|
|
20
|
+
}
|
|
21
|
+
return target._execute.bind(target, prop);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
withIdentity(i) {
|
|
26
|
+
return new Executor({
|
|
27
|
+
identity: i,
|
|
28
|
+
apiBaseUrl: this._apiBaseUrl,
|
|
29
|
+
parseJsonResult: this._parseJsonResult,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
withAuthToken(t) {
|
|
33
|
+
return new Executor({
|
|
34
|
+
authToken: t,
|
|
35
|
+
apiBaseUrl: this._apiBaseUrl,
|
|
36
|
+
parseJsonResult: this._parseJsonResult,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
_execute(method, params) {
|
|
40
|
+
const headers = { "Content-Type": "application/json" };
|
|
41
|
+
|
|
42
|
+
// An Identity instance is provided make a JWT
|
|
43
|
+
if (this._identity !== null) {
|
|
44
|
+
const base64pk = process.env.KEEL_DEFAULT_PK;
|
|
45
|
+
let privateKey = undefined;
|
|
46
|
+
|
|
47
|
+
if (base64pk) {
|
|
48
|
+
privateKey = Buffer.from(base64pk, "base64").toString("utf8");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
headers["Authorization"] =
|
|
52
|
+
"Bearer " +
|
|
53
|
+
jwt.sign({}, privateKey, {
|
|
54
|
+
algorithm: privateKey ? "RS256" : "none",
|
|
55
|
+
expiresIn: 60 * 60 * 24,
|
|
56
|
+
subject: this._identity.id,
|
|
57
|
+
issuer: "keel",
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// If an auth token is provided that can be sent as-is
|
|
62
|
+
if (this._authToken !== null) {
|
|
63
|
+
headers["Authorization"] = "Bearer " + this._authToken;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (params?.scheduled) {
|
|
67
|
+
headers["X-Trigger-Type"] = "scheduled";
|
|
68
|
+
} else {
|
|
69
|
+
headers["X-Trigger-Type"] = "manual";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Use the HTTP JSON API as that returns more friendly errors than
|
|
73
|
+
// the JSON-RPC API.
|
|
74
|
+
return fetch(this._apiBaseUrl + "/" + method, {
|
|
75
|
+
method: "POST",
|
|
76
|
+
body: JSON.stringify(params),
|
|
77
|
+
headers,
|
|
78
|
+
}).then((r) => {
|
|
79
|
+
if (r.status !== 200) {
|
|
80
|
+
// For non-200 first read the response as text
|
|
81
|
+
return r.text().then((t) => {
|
|
82
|
+
let d;
|
|
83
|
+
try {
|
|
84
|
+
d = JSON.parse(t);
|
|
85
|
+
} catch (e) {
|
|
86
|
+
if ("DEBUG" in process.env) {
|
|
87
|
+
console.log(e);
|
|
88
|
+
}
|
|
89
|
+
// If JSON parsing fails then throw an error with the
|
|
90
|
+
// response text as the message
|
|
91
|
+
throw new Error(t);
|
|
92
|
+
}
|
|
93
|
+
// Otherwise throw the parsed JSON error response
|
|
94
|
+
// We override toString as otherwise you get expect errors like:
|
|
95
|
+
// `expected to resolve but rejected with "[object Object]"`
|
|
96
|
+
Object.defineProperty(d, "toString", {
|
|
97
|
+
value: () => t,
|
|
98
|
+
enumerable: false,
|
|
99
|
+
});
|
|
100
|
+
throw d;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (this._parseJsonResult) {
|
|
105
|
+
return r.json();
|
|
106
|
+
} else {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
package/src/JobExecutor.mjs
CHANGED
|
@@ -1,94 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Executor } from "./Executor.mjs";
|
|
2
2
|
|
|
3
|
-
export class JobExecutor {
|
|
3
|
+
export class JobExecutor extends Executor {
|
|
4
4
|
constructor(props) {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
props.apiBaseUrl = process.env.KEEL_TESTING_JOBS_URL;
|
|
6
|
+
props.parseJsonResult = false;
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
// _execute method for any unknown properties. This creates
|
|
10
|
-
// the jobs API we want but in a dynamic way without needing
|
|
11
|
-
// codegen. We then generate the right type definitions for
|
|
12
|
-
// this class in the @teamkeel/testing package.
|
|
13
|
-
return new Proxy(this, {
|
|
14
|
-
get(target, prop) {
|
|
15
|
-
const v = Reflect.get(...arguments);
|
|
16
|
-
if (v !== undefined) {
|
|
17
|
-
return v;
|
|
18
|
-
}
|
|
19
|
-
return target._execute.bind(target, prop);
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
withIdentity(i) {
|
|
24
|
-
return new JobExecutor({ identity: i });
|
|
25
|
-
}
|
|
26
|
-
withAuthToken(t) {
|
|
27
|
-
return new JobExecutor({ authToken: t });
|
|
28
|
-
}
|
|
29
|
-
_execute(method, params) {
|
|
30
|
-
const headers = { "Content-Type": "application/json" };
|
|
31
|
-
|
|
32
|
-
// An Identity instance is provided make a JWT
|
|
33
|
-
if (this._identity !== null) {
|
|
34
|
-
headers["Authorization"] =
|
|
35
|
-
"Bearer " +
|
|
36
|
-
jwt.sign(
|
|
37
|
-
{},
|
|
38
|
-
// Not using a signing algorithm, therefore the private key is undefined
|
|
39
|
-
undefined,
|
|
40
|
-
{
|
|
41
|
-
algorithm: "none",
|
|
42
|
-
expiresIn: 60 * 60 * 24,
|
|
43
|
-
subject: this._identity.id,
|
|
44
|
-
issuer: "keel",
|
|
45
|
-
}
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// If an auth token is provided that can be sent as-is
|
|
50
|
-
if (this._authToken !== null) {
|
|
51
|
-
headers["Authorization"] = "Bearer " + this._authToken;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (params?.scheduled) {
|
|
55
|
-
headers["X-Trigger-Type"] = "scheduled";
|
|
56
|
-
} else {
|
|
57
|
-
headers["X-Trigger-Type"] = "manual";
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return fetch(process.env.KEEL_TESTING_JOBS_URL + "/" + method, {
|
|
61
|
-
method: "POST",
|
|
62
|
-
body: JSON.stringify(params),
|
|
63
|
-
headers,
|
|
64
|
-
}).then((r) => {
|
|
65
|
-
if (r.status !== 200) {
|
|
66
|
-
// For non-200 first read the response as text
|
|
67
|
-
return r.text().then((t) => {
|
|
68
|
-
let d;
|
|
69
|
-
try {
|
|
70
|
-
d = JSON.parse(t);
|
|
71
|
-
} catch (e) {
|
|
72
|
-
if ("DEBUG" in process.env) {
|
|
73
|
-
console.log(e);
|
|
74
|
-
}
|
|
75
|
-
// If JSON parsing fails then throw an error with the
|
|
76
|
-
// response text as the message
|
|
77
|
-
throw new Error(t);
|
|
78
|
-
}
|
|
79
|
-
// Otherwise throw the parsed JSON error response
|
|
80
|
-
// We override toString as otherwise you get expect errors like:
|
|
81
|
-
// `expected to resolve but rejected with "[object Object]"`
|
|
82
|
-
Object.defineProperty(d, "toString", {
|
|
83
|
-
value: () => t,
|
|
84
|
-
enumerable: false,
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
throw d;
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return true;
|
|
92
|
-
});
|
|
8
|
+
super(props);
|
|
93
9
|
}
|
|
94
10
|
}
|
package/src/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { sql } from "kysely";
|
|
2
2
|
export { ActionExecutor } from "./ActionExecutor.mjs";
|
|
3
3
|
export { JobExecutor } from "./JobExecutor.mjs";
|
|
4
|
+
export { SubscriberExecutor } from "./SubscriberExecutor.mjs";
|
|
4
5
|
export { toHaveError } from "./toHaveError.mjs";
|
|
5
6
|
export { toHaveAuthorizationError } from "./toHaveAuthorizationError.mjs";
|
|
@@ -9,9 +9,12 @@ export async function toHaveAuthorizationError(received) {
|
|
|
9
9
|
};
|
|
10
10
|
} catch (err) {
|
|
11
11
|
return {
|
|
12
|
-
pass:
|
|
12
|
+
pass:
|
|
13
|
+
err.code === "ERR_PERMISSION_DENIED" || err.code === "ERR_UNAUTHORIZED",
|
|
13
14
|
message: () =>
|
|
14
|
-
`expected there to be ${
|
|
15
|
+
`expected there to be ${
|
|
16
|
+
isNot ? "no " : ""
|
|
17
|
+
}ERR_PERMISSION_DENIED or ERR_UNAUTHORIZED error`,
|
|
15
18
|
actual: err,
|
|
16
19
|
expected: {
|
|
17
20
|
...err,
|