diff --git a/Cargo.lock b/Cargo.lock
index 89a16ce8e05..e750e4a9f7d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -10,9 +10,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
-version = "1.1.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
@@ -131,9 +131,9 @@ checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
[[package]]
name = "cc"
-version = "1.0.83"
+version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+checksum = "6c6b2562119bf28c3439f7f02db99faf0aa1a8cdfe5772a2ee155d32227239f0"
dependencies = [
"libc",
]
@@ -378,13 +378,13 @@ checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
[[package]]
name = "filetime"
-version = "0.2.22"
+version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
+checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.3.5",
+ "redox_syscall 0.2.16",
"windows-sys 0.48.0",
]
@@ -396,9 +396,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flate2"
-version = "1.0.27"
+version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -554,9 +554,9 @@ checksum = "2c785eefb63ebd0e33416dfcb8d6da0bf27ce752843a45632a67bf10d4d4b5c4"
[[package]]
name = "insta"
-version = "1.33.0"
+version = "1.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aa511b2e298cd49b1856746f6bb73e17036bcd66b25f5e92cdcdbec9bd75686"
+checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc"
dependencies = [
"console",
"lazy_static",
diff --git a/docs/docs/02-concepts/05-simulator.md b/docs/docs/02-concepts/05-simulator.md
index f03312360de..1c028dca775 100644
--- a/docs/docs/02-concepts/05-simulator.md
+++ b/docs/docs/02-concepts/05-simulator.md
@@ -94,6 +94,34 @@ const response = await fn.invoke("hello!");
console.log(response);
```
+### Interacting with the simulation across processes
+
+The simulator also exposes an HTTP server that can be used to interact with the
+simulated application from other processes. To get the URL of the simulator's
+HTTP server, access `sim.url` after the simulator has started.
+
+```typescript
+declare const sim: testing.Simulator;
+
+// ...after the simulator has started
+
+const url = sim.url;
+console.log(url);
+
+const handleId = sim.getResourceConfig("root/Default/cloud.Bucket").attrs.handle;
+console.log(handleId);
+```
+
+In another process, a client can be generated to interact with the simulator. Internally it will behave the same as the resource client, but it will use HTTP requests to communicate with the simulator.
+
+```typescript
+import { cloud, testing } from '@winglang/sdk';
+
+const bucket = testing.makeSimulatorClient("WING_SIMULATOR_URL", "HANDLE_ID") as cloud.IBucketClient;
+const response = await bucket.get("my-key");
+console.log(response);
+```
+
### Debugging
Finally, when you want to understand how Wing resources are working, you may
diff --git a/docs/docs/04-standard-library/02-ex/redis.md b/docs/docs/04-standard-library/02-ex/redis.md
index 3e2931a868a..ed06856a79e 100644
--- a/docs/docs/04-standard-library/02-ex/redis.md
+++ b/docs/docs/04-standard-library/02-ex/redis.md
@@ -36,7 +36,6 @@ new ex.Redis();
| get
| Get value at given key. |
| hget
| Returns the value associated with field in the hash stored at key. |
| hset
| Sets the specified field to respective value in the hash stored at key. |
-| rawClient
| Get raw redis client (currently IoRedis). |
| sadd
| Add the specified members to the set stored at key. |
| set
| Set key value pair. |
| smembers
| Returns all the members of the set value stored at key. |
@@ -132,14 +131,6 @@ value to set at field in key.
---
-##### `rawClient`
-
-```wing
-inflight rawClient(): any
-```
-
-Get raw redis client (currently IoRedis).
-
##### `sadd`
```wing
@@ -263,7 +254,6 @@ new ex.RedisClientBase();
| get
| Get value at given key. |
| hget
| Returns the value associated with field in the hash stored at key. |
| hset
| Sets the specified field to respective value in the hash stored at key. |
-| rawClient
| Get raw redis client (currently IoRedis). |
| sadd
| Add the specified members to the set stored at key. |
| set
| Set key value pair. |
| smembers
| Returns all the members of the set value stored at key. |
@@ -345,14 +335,6 @@ Sets the specified field to respective value in the hash stored at key.
---
-##### `rawClient`
-
-```wing
-rawClient(): any
-```
-
-Get raw redis client (currently IoRedis).
-
##### `sadd`
```wing
diff --git a/examples/tests/sdk_tests/bucket/delete.test.w b/examples/tests/sdk_tests/bucket/delete.test.w
index 9572072f123..e8324b13f16 100644
--- a/examples/tests/sdk_tests/bucket/delete.test.w
+++ b/examples/tests/sdk_tests/bucket/delete.test.w
@@ -9,7 +9,7 @@ test "delete" {
try {
block();
} catch actual {
- assert(actual == expected);
+ assert(actual.contains(expected));
error = true;
}
assert(error);
@@ -34,4 +34,4 @@ test "delete" {
b.delete("file2.txt");
assert(!b.exists("file2.txt"));
-}
\ No newline at end of file
+}
diff --git a/examples/tests/sdk_tests/bucket/metadata.test.w b/examples/tests/sdk_tests/bucket/metadata.test.w
index 3584614b0ec..6bb88233bfd 100644
--- a/examples/tests/sdk_tests/bucket/metadata.test.w
+++ b/examples/tests/sdk_tests/bucket/metadata.test.w
@@ -5,13 +5,14 @@ let b = new cloud.Bucket();
test "metadata" {
b.put("test1.txt", "Foo");
- assert(b.metadata("test1.txt").size == 3);
- assert(b.metadata("test1.txt").contentType == "application/octet-stream");
- assert(b.metadata("test1.txt").lastModified.year >= 2023);
+ let metadata = b.metadata("test1.txt");
+ assert(metadata.size == 3);
+ assert(metadata.contentType == "application/octet-stream");
+ assert(metadata.lastModified.year >= 2023);
try {
b.metadata("no-such-file.txt").lastModified;
} catch e {
- assert(e == "Object does not exist (key=no-such-file.txt).");
+ assert(e.contains("Object does not exist (key=no-such-file.txt)."));
}
}
diff --git a/examples/tests/sdk_tests/bucket/public_url.test.w b/examples/tests/sdk_tests/bucket/public_url.test.w
index 94d8d8d240d..3d151dbe528 100644
--- a/examples/tests/sdk_tests/bucket/public_url.test.w
+++ b/examples/tests/sdk_tests/bucket/public_url.test.w
@@ -11,7 +11,7 @@ test "publicUrl" {
try {
block();
} catch actual {
- assert(actual == expected);
+ assert(actual.contains(expected));
error = true;
}
assert(error);
@@ -33,4 +33,4 @@ test "publicUrl" {
assertThrows(BUCKET_NOT_PUBLIC_ERROR, () => {
privateBucket.publicUrl("file2.txt");
});
-}
\ No newline at end of file
+}
diff --git a/examples/tests/sdk_tests/queue/push.test.w b/examples/tests/sdk_tests/queue/push.test.w
index e6837594ea7..ed80133ed0a 100644
--- a/examples/tests/sdk_tests/queue/push.test.w
+++ b/examples/tests/sdk_tests/queue/push.test.w
@@ -17,14 +17,14 @@ new std.Test(inflight () => {
q.push("");
assert(false);
} catch e {
- assert(e == "Empty messages are not allowed");
+ assert(e.contains("Empty messages are not allowed"));
}
try {
q.push("Foo", "");
assert(false);
} catch e {
- assert(e == "Empty messages are not allowed");
+ assert(e.contains("Empty messages are not allowed"));
}
q.push("Foo");
@@ -47,4 +47,4 @@ new std.Test(inflight () => {
assert(util.waitUntil((): bool => {
return q.approxSize() == 3;
}));
-}, { timeout: 3m }) as "push";
\ No newline at end of file
+}, { timeout: 3m }) as "push";
diff --git a/examples/tests/sdk_tests/schedule/on_tick.test.w b/examples/tests/sdk_tests/schedule/on_tick.test.w
index dc682bd5412..00b27d8c13f 100644
--- a/examples/tests/sdk_tests/schedule/on_tick.test.w
+++ b/examples/tests/sdk_tests/schedule/on_tick.test.w
@@ -7,27 +7,23 @@ let from_rate = new cloud.Schedule( rate: 1m ) as "from_rate";
let c1 = new cloud.Counter() as "c1";
let c2 = new cloud.Counter() as "c2";
-
from_cron.onTick(inflight () => {
- c1.inc();
+ c1.inc();
});
from_rate.onTick(inflight () => {
- c2.inc();
+ c2.inc();
});
-
-// std.Test is used setting the timeout property
new std.Test(inflight () => {
- // counters start at zero
- assert(c1.peek() == 0);
- assert(c2.peek() == 0);
-
- // wait at least one minute
- util.sleep(1.1m);
+ // counters may have been incremented before the test starts
+ let c1val = c1.peek();
+ let c2val = c2.peek();
- // check that both counters have been incremented
- assert(c1.peek() >= 1);
- assert(c2.peek() >= 1);
+ // wait at least one minute
+ util.sleep(1.1m);
-}, std.TestProps { timeout: 2m }) as "on tick is called both for rate and cron schedules";
+ // check that both counters have been incremented
+ assert(c1.peek() >= c1val + 1);
+ assert(c2.peek() >= c2val + 1);
+},timeout: 2m) as "on tick is called both for rate and cron schedules";
diff --git a/examples/tests/sdk_tests/table/get.test.w b/examples/tests/sdk_tests/table/get.test.w
index fe880c281aa..b2b554479ad 100644
--- a/examples/tests/sdk_tests/table/get.test.w
+++ b/examples/tests/sdk_tests/table/get.test.w
@@ -20,7 +20,7 @@ test "get" {
try {
block();
} catch actual {
- assert(actual == expected);
+ assert(actual.contains(expected));
error = true;
}
assert(error);
diff --git a/examples/tests/valid/redis.test.w b/examples/tests/valid/redis.test.w
index 93f8378eeff..a8d355a24a2 100644
--- a/examples/tests/valid/redis.test.w
+++ b/examples/tests/valid/redis.test.w
@@ -18,12 +18,6 @@ queue.setConsumer(inflight (message: str) => {
}, timeout: 3s);
test "testing Redis" {
- // Using raw client
- let connection = r.rawClient();
- connection.set("wing", "does redis");
- let value = connection.get("wing");
- assert(value == "does redis");
-
// Using API
r2.set("wing", "does redis again");
let value2 = r2.get("wing");
diff --git a/libs/wingsdk/.projen/deps.json b/libs/wingsdk/.projen/deps.json
index 5c7159ccc78..cd5947ee388 100644
--- a/libs/wingsdk/.projen/deps.json
+++ b/libs/wingsdk/.projen/deps.json
@@ -295,6 +295,10 @@
"name": "safe-stable-stringify",
"type": "bundled"
},
+ {
+ "name": "undici",
+ "type": "bundled"
+ },
{
"name": "uuid",
"type": "bundled"
diff --git a/libs/wingsdk/.projen/tasks.json b/libs/wingsdk/.projen/tasks.json
index 9b02644fc00..acb844e229e 100644
--- a/libs/wingsdk/.projen/tasks.json
+++ b/libs/wingsdk/.projen/tasks.json
@@ -480,7 +480,7 @@
"exec": "pnpm i --no-frozen-lockfile"
},
{
- "exec": "pnpm update @cdktf/provider-aws @types/aws-lambda @types/express @types/fs-extra @types/mime-types @types/node @types/uuid @typescript-eslint/eslint-plugin @typescript-eslint/parser @vitest/coverage-v8 @winglang/jsii-docgen aws-sdk-client-mock aws-sdk-client-mock-jest bump-pack cdktf-cli constructs eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint-plugin-sort-exports eslint fs-extra jsii-diff jsii-pacmak jsii-rosetta jsii nanoid npm-check-updates prettier projen standard-version ts-node typescript vitest wing-api-checker @aws-sdk/client-cloudwatch-logs @aws-sdk/client-dynamodb @aws-sdk/client-elasticache @aws-sdk/client-lambda @aws-sdk/client-s3 @aws-sdk/client-secrets-manager @aws-sdk/client-sns @aws-sdk/client-sqs @aws-sdk/is-array-buffer @aws-sdk/s3-request-presigner @aws-sdk/types @aws-sdk/util-buffer-from @aws-sdk/util-dynamodb @aws-sdk/util-stream-node @aws-sdk/util-utf8-node @azure/core-paging @azure/identity @azure/storage-blob @types/aws-lambda aws-cdk-lib cdktf cron-parser esbuild-wasm express ioredis jsonschema mime-types nanoid safe-stable-stringify uuid yaml constructs constructs"
+ "exec": "pnpm update @cdktf/provider-aws @types/aws-lambda @types/express @types/fs-extra @types/mime-types @types/node @types/uuid @typescript-eslint/eslint-plugin @typescript-eslint/parser @vitest/coverage-v8 @winglang/jsii-docgen aws-sdk-client-mock aws-sdk-client-mock-jest bump-pack cdktf-cli constructs eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint-plugin-sort-exports eslint fs-extra jsii-diff jsii-pacmak jsii-rosetta jsii nanoid npm-check-updates prettier projen standard-version ts-node typescript vitest wing-api-checker @aws-sdk/client-cloudwatch-logs @aws-sdk/client-dynamodb @aws-sdk/client-elasticache @aws-sdk/client-lambda @aws-sdk/client-s3 @aws-sdk/client-secrets-manager @aws-sdk/client-sns @aws-sdk/client-sqs @aws-sdk/is-array-buffer @aws-sdk/s3-request-presigner @aws-sdk/types @aws-sdk/util-buffer-from @aws-sdk/util-dynamodb @aws-sdk/util-stream-node @aws-sdk/util-utf8-node @azure/core-paging @azure/identity @azure/storage-blob @types/aws-lambda aws-cdk-lib cdktf cron-parser esbuild-wasm express ioredis jsonschema mime-types nanoid safe-stable-stringify undici uuid yaml constructs constructs"
},
{
"exec": "pnpm exec projen"
diff --git a/libs/wingsdk/.projenrc.ts b/libs/wingsdk/.projenrc.ts
index ccfe1890f30..eb8758cb08a 100644
--- a/libs/wingsdk/.projenrc.ts
+++ b/libs/wingsdk/.projenrc.ts
@@ -78,6 +78,7 @@ const project = new cdk.JsiiProject({
// simulator dependencies
"express",
"uuid",
+ "undici",
// using version 3 because starting from version 4, it no longer works with CommonJS.
"nanoid@^3.3.6",
"cron-parser",
diff --git a/libs/wingsdk/package.json b/libs/wingsdk/package.json
index 8af63262534..5d32c9f6de8 100644
--- a/libs/wingsdk/package.json
+++ b/libs/wingsdk/package.json
@@ -109,6 +109,7 @@
"mime-types": "^2.1.35",
"nanoid": "^3.3.6",
"safe-stable-stringify": "^2.4.3",
+ "undici": "^5.26.3",
"uuid": "^8.3.2",
"yaml": "^2.3.2"
},
@@ -142,6 +143,7 @@
"mime-types",
"nanoid",
"safe-stable-stringify",
+ "undici",
"uuid",
"yaml"
],
diff --git a/libs/wingsdk/src/ex/redis.ts b/libs/wingsdk/src/ex/redis.ts
index d516ea481b0..da39bd001a3 100644
--- a/libs/wingsdk/src/ex/redis.ts
+++ b/libs/wingsdk/src/ex/redis.ts
@@ -32,7 +32,6 @@ export abstract class Redis extends Resource {
/** @internal */
public _getInflightOps(): string[] {
return [
- RedisInflightMethods.RAW_CLIENT,
RedisInflightMethods.URL,
RedisInflightMethods.SET,
RedisInflightMethods.GET,
@@ -49,12 +48,6 @@ export abstract class Redis extends Resource {
* Inflight interface for `Redis`.
*/
export interface IRedisClient {
- /**
- * Get raw redis client (currently IoRedis).
- * @inflight
- */
- rawClient(): Promise;
-
/**
* Get url of redis server.
* @inflight
@@ -126,8 +119,6 @@ export interface IRedisClient {
* @internal
*/
export enum RedisInflightMethods {
- /** `Redis.rawClient` */
- RAW_CLIENT = "rawClient",
/** `Redis.url` */
URL = "url",
/** `Redis.set` */
@@ -150,7 +141,10 @@ export enum RedisInflightMethods {
* Base class for `Redis` Client.
*/
export abstract class RedisClientBase implements IRedisClient {
- public abstract rawClient(): Promise;
+ /**
+ * Get raw redis client (currently IoRedis).
+ */
+ protected abstract rawClient(): Promise;
public abstract url(): Promise;
public async set(key: string, value: string): Promise {
diff --git a/libs/wingsdk/src/shared/bundling.ts b/libs/wingsdk/src/shared/bundling.ts
index 468a261104b..ecf0ebaf7da 100644
--- a/libs/wingsdk/src/shared/bundling.ts
+++ b/libs/wingsdk/src/shared/bundling.ts
@@ -10,6 +10,8 @@ export interface Bundle {
hash: string;
}
+const SDK_PATH = normalPath(join(__dirname, "..", ".."));
+
/**
* Bundles a javascript entrypoint into a single file.
* @param entrypoint The javascript entrypoint
@@ -29,6 +31,9 @@ export function createBundle(entrypoint: string, outputDir?: string): Bundle {
nodePaths: process.env.WING_NODE_MODULES
? [normalPath(process.env.WING_NODE_MODULES as string)]
: undefined,
+ alias: {
+ "@winglang/sdk": SDK_PATH,
+ },
minify: false,
platform: "node",
target: "node18",
diff --git a/libs/wingsdk/src/simulator/client.ts b/libs/wingsdk/src/simulator/client.ts
new file mode 100644
index 00000000000..0f5f93ed7ad
--- /dev/null
+++ b/libs/wingsdk/src/simulator/client.ts
@@ -0,0 +1,92 @@
+import { fetch, Agent } from "undici";
+import type {
+ SimulatorServerRequest,
+ SimulatorServerResponse,
+} from "./simulator";
+import { Datetime } from "../std";
+
+// TODO: more robust serialization scheme
+
+export function serializeValue(input: any): string {
+ return JSON.stringify(input, (_key, value) => {
+ if (value instanceof Datetime) {
+ return {
+ $kind: "datetime",
+ day: value.dayOfMonth,
+ hour: value.hours,
+ min: value.min,
+ month: value.month,
+ sec: value.sec,
+ year: value.year,
+ ms: value.ms,
+ tz: value.timezone,
+ };
+ }
+ return value;
+ });
+}
+
+export function deserializeValue(input: string): any {
+ return JSON.parse(input, (_key, value) => {
+ // assumption: Wing APIs don't distinguish between null and undefined, so we can swap them
+ if (value === null) {
+ return undefined;
+ }
+ if (value.$kind === "datetime") {
+ return Datetime.fromComponents({
+ day: value.day,
+ hour: value.hour,
+ min: value.min,
+ month: value.month,
+ sec: value.sec,
+ year: value.year,
+ ms: value.ms,
+ tz: value.tz,
+ });
+ }
+ return value;
+ });
+}
+
+export function makeSimulatorClient(url: string, handle: string) {
+ return new Proxy(
+ {},
+ {
+ get: function (_target, method, _receiver) {
+ return async function (...args: any[]) {
+ const body: SimulatorServerRequest = {
+ handle,
+ method: method as string,
+ args,
+ };
+ let resp;
+ try {
+ resp = await fetch(url + "/v1/call", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(body),
+ dispatcher: new Agent({
+ keepAliveTimeout: 15 * 60 * 1000,
+ keepAliveMaxTimeout: 15 * 60 * 1000,
+ headersTimeout: 15 * 60 * 1000,
+ bodyTimeout: 15 * 60 * 1000,
+ }),
+ });
+ } catch (e) {
+ console.error(e);
+ throw e;
+ }
+
+ let parsed: SimulatorServerResponse = deserializeValue(
+ await resp.text()
+ );
+
+ if (parsed.error) {
+ throw new Error(parsed.error);
+ }
+ return parsed.result;
+ };
+ },
+ }
+ );
+}
diff --git a/libs/wingsdk/src/simulator/index.ts b/libs/wingsdk/src/simulator/index.ts
index ec92e67c9b6..b78ccbbdf55 100644
--- a/libs/wingsdk/src/simulator/index.ts
+++ b/libs/wingsdk/src/simulator/index.ts
@@ -1,3 +1,4 @@
+export * from "./client";
export * from "./simulator";
export * from "./testing";
export * from "./tree";
diff --git a/libs/wingsdk/src/simulator/simulator.ts b/libs/wingsdk/src/simulator/simulator.ts
index a214dfb480a..9cdac2be128 100644
--- a/libs/wingsdk/src/simulator/simulator.ts
+++ b/libs/wingsdk/src/simulator/simulator.ts
@@ -1,5 +1,12 @@
import { existsSync } from "fs";
+import { Server } from "http";
+import { AddressInfo } from "net";
import { join } from "path";
+import {
+ deserializeValue,
+ makeSimulatorClient,
+ serializeValue,
+} from "./client";
import { Tree } from "./tree";
import { SDK_VERSION } from "../constants";
import { ConstructTree, TREE_FILE_PATH } from "../core";
@@ -11,6 +18,8 @@ import { isToken } from "../target-sim/tokens";
const START_ATTEMPT_COUNT = 10;
+const LOCALHOST_ADDRESS = "127.0.0.1";
+
/**
* Props for `Simulator`.
*/
@@ -77,6 +86,11 @@ export interface ISimulatorContext {
*/
readonly resourcePath: string;
+ /**
+ * The url that the simulator server is listening on.
+ */
+ readonly serverUrl: string;
+
/**
* Find a resource simulation by its handle. Throws if the handle isn't valid.
*/
@@ -127,6 +141,8 @@ export class Simulator {
private readonly _traceSubscribers: Array;
private _tree: Tree;
private _connections: ConnectionData[];
+ private _serverUrl: string | undefined;
+ private _server: Server | undefined;
constructor(props: SimulatorProps) {
this.simdir = props.simfile;
@@ -203,6 +219,8 @@ export class Simulator {
...this._config.resources,
];
+ await this.startServer();
+
while (true) {
const next = initQueue.shift();
if (!next) {
@@ -231,6 +249,69 @@ export class Simulator {
this._running = true;
}
+ /**
+ * Start a server that allows any resource to be accessed via HTTP.
+ */
+ public async startServer(): Promise {
+ // import lazily to reduce SDK import time (20ms or so)
+ const express = await import("express").then((m) => m.default);
+ const app = express();
+ app.use(express.json());
+
+ app.post("/v1/call", async (req, res, next) => {
+ try {
+ let request: SimulatorServerRequest = deserializeValue(
+ JSON.stringify(req.body)
+ );
+
+ const { handle, method, args } = request;
+ const resource = this._handles.find(handle);
+
+ try {
+ const result = await (resource as any)[method](...args);
+ res
+ .status(200)
+ .json(
+ JSON.parse(serializeValue({ result })) as SimulatorServerResponse
+ );
+ } catch (err) {
+ if (err instanceof Error) {
+ res.status(500).json({
+ error: err.stack ?? err.message,
+ } as SimulatorServerResponse);
+ } else {
+ res.status(500).json({ error: err } as SimulatorServerResponse);
+ }
+ }
+ } catch (err) {
+ return next(err);
+ }
+ });
+
+ const addrInfo: AddressInfo = await new Promise((resolve, reject) => {
+ this._server = app.listen(0, LOCALHOST_ADDRESS, () => {
+ const addr = this._server?.address();
+ if (addr && typeof addr === "object" && (addr as any).port) {
+ resolve(addr);
+ } else {
+ reject(new Error("No address found"));
+ }
+ });
+ });
+
+ this._serverUrl = `http://${addrInfo.address}:${addrInfo.port}`;
+ }
+
+ /**
+ * The URL that the simulator server is listening on.
+ */
+ public get url(): string {
+ if (!this._serverUrl) {
+ throw new Error("Simulator server is not running.");
+ }
+ return this._serverUrl;
+ }
+
/**
* Stop the simulation and clean up all resources.
*/
@@ -265,6 +346,9 @@ export class Simulator {
this._addTrace(event);
}
+ this._server!.close();
+ this._server!.closeAllConnections();
+
this._handles.reset();
this._running = false;
}
@@ -299,28 +383,28 @@ export class Simulator {
}
/**
- * Get a simulated resource instance.
+ * Get a resource client.
* @returns the resource
*/
public getResource(path: string): any {
- const handle = this.tryGetResource(path);
- if (!handle) {
+ const client = this.tryGetResource(path);
+ if (!client) {
throw new Error(`Resource "${path}" not found.`);
}
- return handle;
+ return client;
}
/**
- * Get a simulated resource instance.
+ * Get a resource client.
* @returns The resource of undefined if not found
*/
public tryGetResource(path: string): any | undefined {
- const handle = this.tryGetResourceConfig(path)?.attrs.handle;
+ const handle: string = this.tryGetResourceConfig(path)?.attrs.handle;
if (!handle) {
return undefined;
}
- return this._handles.find(handle);
+ return makeSimulatorClient(this.url, handle);
}
/**
@@ -422,9 +506,14 @@ export class Simulator {
}
private createContext(resourceConfig: BaseResourceSchema): ISimulatorContext {
+ const serverUrl = this._serverUrl;
+ if (!serverUrl) {
+ throw new Error("Simulator server is not running.");
+ }
return {
simdir: this.simdir,
resourcePath: resourceConfig.path,
+ serverUrl,
findInstance: (handle: string) => {
return this._handles.find(handle);
},
@@ -653,3 +742,27 @@ export interface ConnectionData {
/** A name for the connection. */
readonly name: string;
}
+
+/**
+ * Internal schema for requests to the simulator server's /call endpoint.
+ * Subject to breaking changes.
+ */
+export interface SimulatorServerRequest {
+ /** The resource handle (an ID unique among resources in the simulation). */
+ readonly handle: string;
+ /** The method to call on the resource. */
+ readonly method: string;
+ /** The arguments to the method. */
+ readonly args: any[];
+}
+
+/**
+ * Internal schema for responses from the simulator server's /call endpoint.
+ * Subject to breaking changes.
+ */
+export interface SimulatorServerResponse {
+ /** The result of the method call. */
+ readonly result?: any;
+ /** The error that occurred during the method call. */
+ readonly error?: any;
+}
diff --git a/libs/wingsdk/src/target-sim/function.inflight.ts b/libs/wingsdk/src/target-sim/function.inflight.ts
index 53b55a152fc..bb93b5cc935 100644
--- a/libs/wingsdk/src/target-sim/function.inflight.ts
+++ b/libs/wingsdk/src/target-sim/function.inflight.ts
@@ -42,7 +42,10 @@ export class Function implements IFunctionClient, ISimulatorResourceInstance {
activity: async () => {
const sb = new Sandbox(this.filename, {
context: { $simulator: this.context },
- env: this.env,
+ env: {
+ ...this.env,
+ WING_SIMULATOR_URL: this.context.serverUrl,
+ },
timeout: this.timeout,
log: (_level, message) => {
this.context.addTrace({
diff --git a/libs/wingsdk/src/target-sim/redis.inflight.ts b/libs/wingsdk/src/target-sim/redis.inflight.ts
index 199a8c7dd76..e3d8c755e29 100644
--- a/libs/wingsdk/src/target-sim/redis.inflight.ts
+++ b/libs/wingsdk/src/target-sim/redis.inflight.ts
@@ -55,7 +55,7 @@ export class Redis
await runCommand("docker", ["rm", "-f", `${this.containerName}`]);
}
- public async rawClient(): Promise {
+ protected async rawClient(): Promise {
if (this.connection) {
return this.connection;
}
diff --git a/libs/wingsdk/src/target-sim/service.inflight.ts b/libs/wingsdk/src/target-sim/service.inflight.ts
index bb2b3a15332..e6f02fa1167 100644
--- a/libs/wingsdk/src/target-sim/service.inflight.ts
+++ b/libs/wingsdk/src/target-sim/service.inflight.ts
@@ -22,7 +22,10 @@ export class Service implements IServiceClient, ISimulatorResourceInstance {
this.entrypoint = resolve(context.simdir, props.sourceCodeFile);
this.autoStart = props.autoStart;
this.sandbox = new Sandbox(this.entrypoint, {
- env: props.environmentVariables,
+ env: {
+ ...props.environmentVariables,
+ WING_SIMULATOR_URL: context.serverUrl,
+ },
context: { $simulator: this.context },
log: (_level, message) => {
this.context.addTrace({
diff --git a/libs/wingsdk/src/target-sim/util.ts b/libs/wingsdk/src/target-sim/util.ts
index 0965e3dc02c..3398d5dcd9a 100644
--- a/libs/wingsdk/src/target-sim/util.ts
+++ b/libs/wingsdk/src/target-sim/util.ts
@@ -43,13 +43,20 @@ export function bindSimulatorResource(
export function makeSimulatorJsClient(filename: string, resource: Resource) {
const type = basename(filename).split(".")[0];
const env = makeEnvVarName(type, resource);
- return `(function(env) {
- let handle = process.env[env];
+
+ // return an object where calling any method will make a request to the simulator server
+ return `(function() {
+ const handle = process.env.${env};
if (!handle) {
- throw new Error("Missing environment variable: " + env);
+ throw new Error("Missing environment variable: ${env}");
+ }
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error("Missing environment variable: WING_SIMULATOR_URL");
}
- return $simulator.findInstance(handle);
-})("${env}")`;
+
+ return require("@winglang/sdk").simulator.makeSimulatorClient(simulatorUrl, handle);
+})()`;
}
// helper function to convert duration to a cron string
diff --git a/libs/wingsdk/src/target-tf-aws/redis.inflight.ts b/libs/wingsdk/src/target-tf-aws/redis.inflight.ts
index fc1e4061d2f..6e2e9b752aa 100644
--- a/libs/wingsdk/src/target-tf-aws/redis.inflight.ts
+++ b/libs/wingsdk/src/target-tf-aws/redis.inflight.ts
@@ -48,7 +48,7 @@ export class RedisClient extends RedisClientBase {
return cacheNode.Endpoint.Address!;
}
- public async rawClient(): Promise {
+ protected async rawClient(): Promise {
if (!this.clusterId) {
throw new Error("No cluster id provided");
}
diff --git a/libs/wingsdk/test/simulator/__snapshots__/simulator.test.ts.snap b/libs/wingsdk/test/simulator/__snapshots__/simulator.test.ts.snap
index c635ef446a0..5efebe83114 100644
--- a/libs/wingsdk/test/simulator/__snapshots__/simulator.test.ts.snap
+++ b/libs/wingsdk/test/simulator/__snapshots__/simulator.test.ts.snap
@@ -87,7 +87,6 @@ exports[`run all tests > single test 1`] = `
{
"data": {
"message": "Invoke (payload=\\"\\").",
- "result": undefined,
"status": "success",
},
"sourcePath": "root/test/Handler",
@@ -118,7 +117,6 @@ exports[`run single test > happy path 1`] = `
{
"data": {
"message": "Invoke (payload=\\"\\").",
- "result": undefined,
"status": "success",
},
"sourcePath": "root/test/Handler",
@@ -157,7 +155,7 @@ exports[`run single test > test failure 1`] = `
},
{
"data": {
- "error": [Error: test failed],
+ "error": {},
"message": "Invoke (payload=\\"\\").",
"status": "failure",
},
diff --git a/libs/wingsdk/test/simulator/simulator.test.ts b/libs/wingsdk/test/simulator/simulator.test.ts
index 7ae3bd0afcb..6d46903516c 100644
--- a/libs/wingsdk/test/simulator/simulator.test.ts
+++ b/libs/wingsdk/test/simulator/simulator.test.ts
@@ -1,9 +1,9 @@
import { Construct } from "constructs";
import { test, expect, describe } from "vitest";
-import { Bucket, ITestRunnerClient, TestResult } from "../../src/cloud";
+import { Bucket } from "../../src/cloud";
import { InflightBindings } from "../../src/core";
import { Testing } from "../../src/simulator";
-import { Test } from "../../src/std";
+import { ITestRunnerClient, Test, TestResult } from "../../src/std";
import { SimApp } from "../sim-app";
describe("run single test", () => {
diff --git a/libs/wingsdk/test/target-sim/__snapshots__/bucket.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/bucket.test.ts.snap
index 5e0b9ad89cb..8e39678bdfb 100644
--- a/libs/wingsdk/test/target-sim/__snapshots__/bucket.test.ts.snap
+++ b/libs/wingsdk/test/target-sim/__snapshots__/bucket.test.ts.snap
@@ -1,6 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-exports[`bucket on event creates 3 topics, and sends the right event and key in the event handlers 1`] = `
+exports[`bucket on event creates 3 topics, and sends the right event and key in the event handlers 1`] = `
[
"wingsdk.cloud.TestRunner created.",
"wingsdk.cloud.Topic created.",
@@ -575,7 +575,6 @@ exports[`update an object in bucket 1`] = `
"Invoke (payload=\\"greeting.txt\\").",
"Subscriber error: TypeError: this.handler.handle is not a function",
"Put (key=greeting.txt).",
- "Put (key=greeting.txt).",
"wingsdk.sim.EventMapping deleted.",
"wingsdk.cloud.Function deleted.",
"wingsdk.cloud.Bucket deleted.",
diff --git a/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap
index ff8aee06aee..380304cb7fd 100644
--- a/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap
+++ b/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap
@@ -18,20 +18,30 @@ return class Handler {
}
};
})())({
-counter: (function(env) {
- let handle = process.env[env];
+counter: (function() {
+ const handle = process.env.COUNTER_HANDLE_4ecd8d46;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: COUNTER_HANDLE_4ecd8d46\\");
}
- return $simulator.findInstance(handle);
-})(\\"COUNTER_HANDLE_4ecd8d46\\"),
-bucket: (function(env) {
- let handle = process.env[env];
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
+ }
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})(),
+bucket: (function() {
+ const handle = process.env.BUCKET_HANDLE_5f2a41c8;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_5f2a41c8\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_5f2a41c8\\")
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
+ }
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})()
}), args: {} })).handle(event);
};",
"connections.json": {
diff --git a/libs/wingsdk/test/target-sim/__snapshots__/function.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/function.test.ts.snap
index 88895a88d58..dd000b0faab 100644
--- a/libs/wingsdk/test/target-sim/__snapshots__/function.test.ts.snap
+++ b/libs/wingsdk/test/target-sim/__snapshots__/function.test.ts.snap
@@ -628,7 +628,7 @@ return class Handler {
}
async handle() {
- return fetch;
+ return typeof fetch;
}
};
@@ -648,7 +648,7 @@ return class Handler {
async handle() {
const c = require(\\"crypto\\");
- return c.createHash;
+ return typeof c.createHash;
}
};
diff --git a/libs/wingsdk/test/target-sim/__snapshots__/immutable-capture.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/immutable-capture.test.ts.snap
index f4967452ddd..0338841f29e 100644
--- a/libs/wingsdk/test/target-sim/__snapshots__/immutable-capture.test.ts.snap
+++ b/libs/wingsdk/test/target-sim/__snapshots__/immutable-capture.test.ts.snap
@@ -126,19 +126,29 @@ if (!(await this.my_buckets[1].get(\\"foo\\") === \\"bar\\")) { throw new Error(
}
};
})())({
-my_buckets: [(function(env) {
- let handle = process.env[env];
+my_buckets: [(function() {
+ const handle = process.env.BUCKET_HANDLE_4fecd6d0;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_4fecd6d0\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_4fecd6d0\\"),(function(env) {
- let handle = process.env[env];
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
+ }
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})(),(function() {
+ const handle = process.env.BUCKET_HANDLE_300e8055;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_300e8055\\");
+ }
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_300e8055\\")]
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})()]
})).handle(event);
};",
"connections.json": {
@@ -1032,19 +1042,29 @@ if (!(await foo.get(\\"hello.txt\\") === \\"world\\")) { throw new Error(\`asser
}
};
})())({
-my_map: new Map([[\\"foo\\",(function(env) {
- let handle = process.env[env];
+my_map: new Map([[\\"foo\\",(function() {
+ const handle = process.env.BUCKET_HANDLE_4fecd6d0;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_4fecd6d0\\");
+ }
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_4fecd6d0\\")],[\\"bar\\",(function(env) {
- let handle = process.env[env];
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})()],[\\"bar\\",(function() {
+ const handle = process.env.BUCKET_HANDLE_300e8055;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_300e8055\\");
+ }
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_300e8055\\")]])
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})()]])
})).handle(event);
};",
"connections.json": {
@@ -1835,37 +1855,62 @@ if (!(await bar.get(\\"foo\\") === \\"bar\\")) { throw new Error(\`assertion fai
}
};
})())({
-my_struct: {\\"bucky\\": (function(env) {
- let handle = process.env[env];
+my_struct: {\\"bucky\\": (function() {
+ const handle = process.env.BUCKET_HANDLE_4fecd6d0;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_4fecd6d0\\");
+ }
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_4fecd6d0\\"),\\"mapy\\": new Map([[\\"foo\\",(function(env) {
- let handle = process.env[env];
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})(),\\"mapy\\": new Map([[\\"foo\\",(function() {
+ const handle = process.env.BUCKET_HANDLE_300e8055;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_300e8055\\");
+ }
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_300e8055\\")],[\\"bar\\",(function(env) {
- let handle = process.env[env];
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})()],[\\"bar\\",(function() {
+ const handle = process.env.BUCKET_HANDLE_0120daf4;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_0120daf4\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_0120daf4\\")]]),\\"arry\\": {\\"boom\\": [(function(env) {
- let handle = process.env[env];
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
+ }
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})()]]),\\"arry\\": {\\"boom\\": [(function() {
+ const handle = process.env.BUCKET_HANDLE_ea7944ef;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_ea7944ef\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_ea7944ef\\"),(function(env) {
- let handle = process.env[env];
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
+ }
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})(),(function() {
+ const handle = process.env.BUCKET_HANDLE_1d7ab674;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: BUCKET_HANDLE_1d7ab674\\");
}
- return $simulator.findInstance(handle);
-})(\\"BUCKET_HANDLE_1d7ab674\\")],},}
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
+ }
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})()],},}
})).handle(event);
};",
"connections.json": {
diff --git a/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap
index 2a44d4d5a81..f84af896ca9 100644
--- a/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap
+++ b/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap
@@ -800,7 +800,7 @@ exports[`queue batch size of 2, purge the queue 2`] = `
}
`;
-exports[`queue with one subscriber, batch size of 5 1`] = `
+exports[`queue with one subscriber, batch size of 5, should get processed in two batches 1`] = `
{
".wing/function_c8ab799f.js": "\\"use strict\\";
exports.handler = async function(event) {
@@ -812,22 +812,22 @@ return class Handler {
}
}
async handle() {
- await this.queue.push(\\"A\\");
- await this.queue.push(\\"B\\");
- await this.queue.push(\\"C\\");
- await this.queue.push(\\"D\\");
- await this.queue.push(\\"E\\");
- await this.queue.push(\\"F\\");
+ await this.queue.push(\\"A\\", \\"B\\", \\"C\\", \\"D\\", \\"E\\", \\"F\\");
}
};
})())({
-queue: (function(env) {
- let handle = process.env[env];
+queue: (function() {
+ const handle = process.env.QUEUE_HANDLE_54fcf4cd;
if (!handle) {
- throw new Error(\\"Missing environment variable: \\" + env);
+ throw new Error(\\"Missing environment variable: QUEUE_HANDLE_54fcf4cd\\");
}
- return $simulator.findInstance(handle);
-})(\\"QUEUE_HANDLE_54fcf4cd\\")
+ const simulatorUrl = process.env.WING_SIMULATOR_URL;
+ if (!simulatorUrl) {
+ throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\");
+ }
+
+ return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle);
+})()
})).handle(event);
};",
".wing/my_queue-setconsumer-e645076f_c8ddc1ce.js": "\\"use strict\\";
diff --git a/libs/wingsdk/test/target-sim/bucket.test.ts b/libs/wingsdk/test/target-sim/bucket.test.ts
index 29053341e45..f42acb07e83 100644
--- a/libs/wingsdk/test/target-sim/bucket.test.ts
+++ b/libs/wingsdk/test/target-sim/bucket.test.ts
@@ -47,25 +47,14 @@ test("update an object in bucket", async () => {
const VALUE = JSON.stringify({ msg: "Hello world!" });
// WHEN
- // @ts-expect-error - private method
- const notifyListeners = vi.spyOn(client, "notifyListeners");
-
await client.put(KEY, VALUE);
- expect(notifyListeners).toBeCalledWith(cloud.BucketEventType.CREATE, KEY);
-
- await client.put(KEY, JSON.stringify({ msg: "another msg" }));
- expect(notifyListeners).toBeCalledWith(cloud.BucketEventType.UPDATE, KEY);
- expect(Object.keys((client as any).topicHandlers)).toMatchObject([
- BucketEventType.CREATE,
- ]);
// THEN
await s.stop();
- expect(notifyListeners).toBeCalledTimes(2);
expect(listMessages(s)).toMatchSnapshot();
});
-test("bucket on event creates 3 topics, and sends the right event and key in the event handlers ", async () => {
+test("bucket on event creates 3 topics, and sends the right event and key in the event handlers", async () => {
// GIVEN
const app = new SimApp();
const bucket = cloud.Bucket._newBucket(app, "my_bucket");
@@ -73,9 +62,9 @@ test("bucket on event creates 3 topics, and sends the right event and key in the
const testInflight = Testing.makeHandler(
app,
"inflight_test",
- `async handle(key, event) { await this.bucket.put(key, event); }`,
+ `async handle(key, event) { await this.logBucket.put(key, event); }`,
{
- bucket: {
+ logBucket: {
obj: logBucket,
ops: [cloud.BucketInflightMethods.PUT],
},
@@ -88,12 +77,6 @@ test("bucket on event creates 3 topics, and sends the right event and key in the
const client = s.getResource("/my_bucket") as cloud.IBucketClient;
const logClient = s.getResource("/log_bucket") as cloud.IBucketClient;
- expect(Object.keys((client as any).topicHandlers)).toMatchObject([
- BucketEventType.CREATE,
- BucketEventType.UPDATE,
- BucketEventType.DELETE,
- ]);
-
// THEN
await client.put("a", "1");
expect(await logClient.get("a")).toBe(BucketEventType.CREATE);
@@ -167,8 +150,6 @@ test("put and get Json object from bucket", async () => {
const VALUE = { msg: "Hello world!" };
// WHEN
-
- const notifyListeners = vi.spyOn(client as any, "notifyListeners");
await client.putJson(KEY, VALUE as any);
const response = await client.getJson("greeting.json");
@@ -178,7 +159,6 @@ test("put and get Json object from bucket", async () => {
expect(response).toEqual(VALUE);
expect(listMessages(s)).toMatchSnapshot();
expect(app.snapshot()).toMatchSnapshot();
- expect(notifyListeners).toBeCalledWith(cloud.BucketEventType.CREATE, KEY);
});
test("put multiple objects and list all from bucket", async () => {
@@ -351,20 +331,9 @@ test("removing a key will call onDelete method", async () => {
await client.put(fileName, JSON.stringify({ msg: "Hello world!" }));
// delete file
- //@ts-expect-error
- const notifyListeners = vi.spyOn(client, "notifyListeners");
const response = await client.delete(fileName);
-
- expect(Object.keys((client as any).topicHandlers)).toMatchObject([
- BucketEventType.DELETE,
- ]);
-
await s.stop();
- expect(notifyListeners).toBeCalledWith(
- cloud.BucketEventType.DELETE,
- fileName
- );
expect(response).toEqual(undefined);
expect(listMessages(s)).toMatchSnapshot();
});
@@ -529,8 +498,7 @@ test("can add file in preflight", async () => {
});
test("Given a non public bucket when reaching to a key public url it should throw an error", async () => {
- //GIVEN
- let error;
+ // GIVEN
const app = new SimApp();
cloud.Bucket._newBucket(app, "my_bucket");
@@ -539,23 +507,15 @@ test("Given a non public bucket when reaching to a key public url it should thro
const KEY = "KEY";
- // WHEN
- try {
- await client.publicUrl(KEY);
- } catch (err) {
- error = err;
- }
-
// THEN
- expect(error?.message).toBe(
- "Cannot provide public url for a non-public bucket"
+ await expect(() => client.publicUrl(KEY)).rejects.toThrowError(
+ /Cannot provide public url for a non-public bucket/
);
await s.stop();
});
test("Given a public bucket when reaching to a non existent key, public url it should throw an error", async () => {
- //GIVEN
- let error;
+ // GIVEN
const app = new SimApp();
cloud.Bucket._newBucket(app, "my_bucket", { public: true });
@@ -564,21 +524,14 @@ test("Given a public bucket when reaching to a non existent key, public url it s
const KEY = "KEY";
- // WHEN
- try {
- await client.publicUrl(KEY);
- } catch (err) {
- error = err;
- }
-
- expect(error?.message).toBe(
- "Cannot provide public url for an non-existent key (key=KEY)"
- );
// THEN
+ await expect(() => client.publicUrl(KEY)).rejects.toThrowError(
+ /Cannot provide public url for an non-existent key/
+ );
await s.stop();
});
-test("Given a public bucket, when giving one of its keys, we should get it's public url", async () => {
+test("Given a public bucket, when giving one of its keys, we should get its public url", async () => {
// GIVEN
const app = new SimApp();
cloud.Bucket._newBucket(app, "my_bucket", { public: true });
@@ -595,8 +548,8 @@ test("Given a public bucket, when giving one of its keys, we should get it's pub
// THEN
await s.stop();
- const filePath = `${client.fileDir}/${KEY}`;
- expect(response).toEqual(url.pathToFileURL(filePath).href);
+ // file paths are different on windows and linux
+ expect(response.endsWith("KEY")).toBe(true);
});
test("check if an object exists in the bucket", async () => {
diff --git a/libs/wingsdk/test/target-sim/file-counter.test.ts b/libs/wingsdk/test/target-sim/file-counter.test.ts
index ba5e41a68b4..59b48c35032 100644
--- a/libs/wingsdk/test/target-sim/file-counter.test.ts
+++ b/libs/wingsdk/test/target-sim/file-counter.test.ts
@@ -6,64 +6,68 @@ import { Testing } from "../../src/simulator";
import { IResource, Trace } from "../../src/std";
import { SimApp } from "../sim-app";
-test("can create sequential files in a bucket", async () => {
- // GIVEN
- class HelloWorld extends Construct {
- public readonly processor: IResource;
+test(
+ "can create sequential files in a bucket",
+ async () => {
+ // GIVEN
+ class HelloWorld extends Construct {
+ public readonly processor: IResource;
- constructor(scope: Construct, id: string) {
- super(scope, id);
+ constructor(scope: Construct, id: string) {
+ super(scope, id);
- const counter = cloud.Counter._newCounter(this, "Counter", {
- initial: 1000,
- });
- const bucket = cloud.Bucket._newBucket(this, "Bucket");
- const queue = cloud.Queue._newQueue(this, "Queue");
- const processor = Testing.makeHandler(
- this,
- "Processor",
- `async handle(event) {
+ const counter = cloud.Counter._newCounter(this, "Counter", {
+ initial: 1000,
+ });
+ const bucket = cloud.Bucket._newBucket(this, "Bucket");
+ const queue = cloud.Queue._newQueue(this, "Queue");
+ const processor = Testing.makeHandler(
+ this,
+ "Processor",
+ `async handle(event) {
let next = await this.counter.inc();
let key = "file-" + next + ".txt";
await this.bucket.put(key, event);
}`,
- {
- counter: {
- obj: counter,
- ops: [cloud.CounterInflightMethods.INC],
- },
- bucket: {
- obj: bucket,
- ops: [cloud.BucketInflightMethods.PUT],
- },
- }
- );
- this.processor = queue.setConsumer(processor);
+ {
+ counter: {
+ obj: counter,
+ ops: [cloud.CounterInflightMethods.INC],
+ },
+ bucket: {
+ obj: bucket,
+ ops: [cloud.BucketInflightMethods.PUT],
+ },
+ }
+ );
+ this.processor = queue.setConsumer(processor);
+ }
}
- }
- const app = new SimApp();
- const helloWorld = new HelloWorld(app, "HelloWorld");
+ const app = new SimApp();
+ const helloWorld = new HelloWorld(app, "HelloWorld");
- const s = await app.startSimulator();
+ const s = await app.startSimulator();
- const pusher = s.getResource("/HelloWorld/Queue") as cloud.IQueueClient;
+ const pusher = s.getResource("/HelloWorld/Queue") as cloud.IQueueClient;
- // WHEN
- const traceCheck = (trace: Trace) =>
- trace.sourcePath === helloWorld.processor.node.path &&
- trace.data.status === "success";
+ // WHEN
+ const traceCheck = (trace: Trace) =>
+ trace.sourcePath === helloWorld.processor.node.path &&
+ trace.data.status === "success";
- await pusher.push("kachow!");
- await waitUntilTraceCount(s, 1, traceCheck);
- await pusher.push("zoom!");
- await waitUntilTraceCount(s, 2, traceCheck);
+ await pusher.push("kachow!");
+ await waitUntilTraceCount(s, 1, traceCheck);
+ await pusher.push("zoom!");
+ await waitUntilTraceCount(s, 2, traceCheck);
- // THEN
- const bucket = s.getResource("/HelloWorld/Bucket") as cloud.IBucketClient;
- await expect(bucket.get("file-1000.txt")).resolves.toEqual("kachow!");
- await expect(bucket.get("file-1001.txt")).resolves.toEqual("zoom!");
- await s.stop();
+ // THEN
+ const bucket = s.getResource("/HelloWorld/Bucket") as cloud.IBucketClient;
+ await expect(bucket.get("file-1000.txt")).resolves.toEqual("kachow!");
+ await expect(bucket.get("file-1001.txt")).resolves.toEqual("zoom!");
+ await s.stop();
- expect(app.snapshot()).toMatchSnapshot();
-});
+ expect(app.snapshot()).toMatchSnapshot();
+ },
+ { timeout: 20000 }
+);
diff --git a/libs/wingsdk/test/target-sim/function.test.ts b/libs/wingsdk/test/target-sim/function.test.ts
index fef87446d21..2468d26d5d2 100644
--- a/libs/wingsdk/test/target-sim/function.test.ts
+++ b/libs/wingsdk/test/target-sim/function.test.ts
@@ -210,12 +210,12 @@ test("runtime environment tests", async () => {
// check that fetch is a function (we can't really make network calls here)
const fetchFn = app.newCloudFunction(`
- return fetch;
+ return typeof fetch;
`);
const cryptoFn = app.newCloudFunction(`
const c = require("crypto");
- return c.createHash;
+ return typeof c.createHash;
`);
// check that we can import ESM modules
@@ -226,9 +226,9 @@ test("runtime environment tests", async () => {
// THEN
const s = await app.startSimulator();
- expect(await cryptoFn(s)).toBeTypeOf("function");
+ expect(await cryptoFn(s)).toEqual("function");
expect(await urlSearchParamsFn(s)).toBe("api");
- expect(await fetchFn(s)).toBeTypeOf("function");
+ expect(await fetchFn(s)).toEqual("function");
expect(await esmModulesFn(s)).toHaveLength(21);
await s.stop();
diff --git a/libs/wingsdk/test/target-sim/immutable-capture.test.ts b/libs/wingsdk/test/target-sim/immutable-capture.test.ts
index dcce10c8a1f..27f5ae13f13 100644
--- a/libs/wingsdk/test/target-sim/immutable-capture.test.ts
+++ b/libs/wingsdk/test/target-sim/immutable-capture.test.ts
@@ -2,7 +2,7 @@ import { Construct } from "constructs";
import { test, expect } from "vitest";
import { Bucket } from "../../src/cloud";
import { Function, IFunctionClient } from "../../src/cloud/function";
-import { InflightBindings, NodeJsCode } from "../../src/core/inflight";
+import { InflightBindings } from "../../src/core/inflight";
import { Testing } from "../../src/simulator";
import { Duration } from "../../src/std";
import { SimApp } from "../sim-app";
diff --git a/libs/wingsdk/test/target-sim/queue.test.ts b/libs/wingsdk/test/target-sim/queue.test.ts
index ee930800981..2644854f2bb 100644
--- a/libs/wingsdk/test/target-sim/queue.test.ts
+++ b/libs/wingsdk/test/target-sim/queue.test.ts
@@ -111,7 +111,7 @@ test("queue batch size of 2, purge the queue", async () => {
expect(app.snapshot()).toMatchSnapshot();
});
-test("queue with one subscriber, batch size of 5", async () => {
+test("queue with one subscriber, batch size of 5, should get processed in two batches", async () => {
// GIVEN
const app = new SimApp();
@@ -125,12 +125,7 @@ test("queue with one subscriber, batch size of 5", async () => {
"OnDeployHandler",
`\
async handle() {
- await this.queue.push("A");
- await this.queue.push("B");
- await this.queue.push("C");
- await this.queue.push("D");
- await this.queue.push("E");
- await this.queue.push("F");
+ await this.queue.push("A", "B", "C", "D", "E", "F");
}`,
{
queue: {
diff --git a/libs/wingsdk/test/target-sim/redis.test.ts b/libs/wingsdk/test/target-sim/redis.test.ts
index 8b9debff46b..2588bcf2904 100644
--- a/libs/wingsdk/test/target-sim/redis.test.ts
+++ b/libs/wingsdk/test/target-sim/redis.test.ts
@@ -1,4 +1,4 @@
-import { Redis as IoRedis } from "ioredis";
+// import { Redis as IoRedis } from "ioredis";
import { test, expect } from "vitest";
import * as ex from "../../src/ex";
import { SimApp } from "../sim-app";
@@ -22,21 +22,6 @@ test("create a Redis resource", async () => {
expect(app.snapshot()).toMatchSnapshot();
});
-test("access a Redis resource", async () => {
- // GIVEN
- const app = new SimApp();
- ex.Redis._newRedis(app, "my_redis");
-
- // THEN
- await app._withSimulator(async (s) => {
- const client = s.getResource("/my_redis") as ex.IRedisClient;
- expect((await client.url()).startsWith("redis://")).toBeTruthy();
- const redisClient = (await client.rawClient()) as IoRedis;
- await redisClient.set("foo", "bar");
- expect(await redisClient.get("foo")).toEqual("bar");
- });
-});
-
test("can set and get a value", async () => {
// GIVEN
const app = new SimApp();
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2e07f59a972..f43599b2d7e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1238,6 +1238,9 @@ importers:
safe-stable-stringify:
specifier: ^2.4.3
version: 2.4.3
+ undici:
+ specifier: ^5.26.3
+ version: 5.26.3
uuid:
specifier: ^8.3.2
version: 8.3.2
@@ -4887,6 +4890,11 @@ packages:
resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==}
dev: true
+ /@fastify/busboy@2.0.0:
+ resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==}
+ engines: {node: '>=14'}
+ dev: false
+
/@floating-ui/core@1.4.1:
resolution: {integrity: sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==}
dependencies:
@@ -13275,7 +13283,7 @@ packages:
dependencies:
semver: 7.5.4
shelljs: 0.8.5
- typescript: 5.3.0-dev.20231012
+ typescript: 5.3.0-dev.20231013
dev: true
/dset@3.1.2:
@@ -22712,8 +22720,8 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
- /typescript@5.3.0-dev.20231012:
- resolution: {integrity: sha512-k/m+QK/2eVsPMAao4I28Cv2Y9WzUKFVhRqvFGZ3CIXc0lrMkw/1pSA+8tp7IMw1ecxoa1myFql1tmCUrMKCbzA==}
+ /typescript@5.3.0-dev.20231013:
+ resolution: {integrity: sha512-ZhuwwWpJ9Hec2JJaS0yOJOjkLDu6lm/PXjniirFFcFBArD5HA3K8P31XxPmwonBhk7oznUbhdIDu8LEYha9Kxw==}
engines: {node: '>=14.17'}
hasBin: true
dev: true
@@ -22749,6 +22757,13 @@ packages:
resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==}
dev: true
+ /undici@5.26.3:
+ resolution: {integrity: sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw==}
+ engines: {node: '>=14.0'}
+ dependencies:
+ '@fastify/busboy': 2.0.0
+ dev: false
+
/unicode-canonical-property-names-ecmascript@2.0.0:
resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==}
engines: {node: '>=4'}
diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/delete.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/delete.test.w_compile_tf-aws.md
index e25e9e02388..e7c7b05a0e9 100644
--- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/delete.test.w_compile_tf-aws.md
+++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/delete.test.w_compile_tf-aws.md
@@ -18,7 +18,7 @@ module.exports = function({ $b }) {
}
catch ($error_actual) {
const actual = $error_actual.message;
- {((cond) => {if (!cond) throw new Error("assertion failed: actual == expected")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(actual,expected)))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: actual.contains(expected)")})(actual.includes(expected))};
error = true;
}
{((cond) => {if (!cond) throw new Error("assertion failed: error")})(error)};
diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/metadata.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/metadata.test.w_compile_tf-aws.md
index 27820f5d32f..30db872bae4 100644
--- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/metadata.test.w_compile_tf-aws.md
+++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/metadata.test.w_compile_tf-aws.md
@@ -12,15 +12,16 @@ module.exports = function({ $b }) {
}
async handle() {
(await $b.put("test1.txt","Foo"));
- {((cond) => {if (!cond) throw new Error("assertion failed: b.metadata(\"test1.txt\").size == 3")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $b.metadata("test1.txt")).size,3)))};
- {((cond) => {if (!cond) throw new Error("assertion failed: b.metadata(\"test1.txt\").contentType == \"application/octet-stream\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $b.metadata("test1.txt")).contentType,"application/octet-stream")))};
- {((cond) => {if (!cond) throw new Error("assertion failed: b.metadata(\"test1.txt\").lastModified.year >= 2023")})(((await $b.metadata("test1.txt")).lastModified.year >= 2023))};
+ const metadata = (await $b.metadata("test1.txt"));
+ {((cond) => {if (!cond) throw new Error("assertion failed: metadata.size == 3")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(metadata.size,3)))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: metadata.contentType == \"application/octet-stream\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(metadata.contentType,"application/octet-stream")))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: metadata.lastModified.year >= 2023")})((metadata.lastModified.year >= 2023))};
try {
(await $b.metadata("no-such-file.txt")).lastModified;
}
catch ($error_e) {
const e = $error_e.message;
- {((cond) => {if (!cond) throw new Error("assertion failed: e == \"Object does not exist (key=no-such-file.txt).\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(e,"Object does not exist (key=no-such-file.txt).")))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: e.contains(\"Object does not exist (key=no-such-file.txt).\")")})(e.includes("Object does not exist (key=no-such-file.txt)."))};
}
}
}
diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.test.w_compile_tf-aws.md
index 492aaa58a31..1d15d4d8a02 100644
--- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.test.w_compile_tf-aws.md
+++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.test.w_compile_tf-aws.md
@@ -18,7 +18,7 @@ module.exports = function({ $http_Util, $privateBucket, $publicBucket, $util_Uti
}
catch ($error_actual) {
const actual = $error_actual.message;
- {((cond) => {if (!cond) throw new Error("assertion failed: actual == expected")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(actual,expected)))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: actual.contains(expected)")})(actual.includes(expected))};
error = true;
}
{((cond) => {if (!cond) throw new Error("assertion failed: error")})(error)};
diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/queue/push.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/queue/push.test.w_compile_tf-aws.md
index ba2c5a49154..c4ecc0c8587 100644
--- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/queue/push.test.w_compile_tf-aws.md
+++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/queue/push.test.w_compile_tf-aws.md
@@ -18,7 +18,7 @@ module.exports = function({ $q, $std_Duration, $util_Util }) {
}
catch ($error_e) {
const e = $error_e.message;
- {((cond) => {if (!cond) throw new Error("assertion failed: e == \"Empty messages are not allowed\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(e,"Empty messages are not allowed")))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: e.contains(\"Empty messages are not allowed\")")})(e.includes("Empty messages are not allowed"))};
}
try {
(await $q.push("Foo",""));
@@ -26,7 +26,7 @@ module.exports = function({ $q, $std_Duration, $util_Util }) {
}
catch ($error_e) {
const e = $error_e.message;
- {((cond) => {if (!cond) throw new Error("assertion failed: e == \"Empty messages are not allowed\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(e,"Empty messages are not allowed")))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: e.contains(\"Empty messages are not allowed\")")})(e.includes("Empty messages are not allowed"))};
}
(await $q.push("Foo"));
{((cond) => {if (!cond) throw new Error("assertion failed: util.waitUntil((): bool => {\n return q.approxSize() == 1;\n })")})((await $util_Util.waitUntil(async () => {
diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/schedule/on_tick.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/schedule/on_tick.test.w_compile_tf-aws.md
index 8bafbad135f..e179fcfca09 100644
--- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/schedule/on_tick.test.w_compile_tf-aws.md
+++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/schedule/on_tick.test.w_compile_tf-aws.md
@@ -49,11 +49,11 @@ module.exports = function({ $c1, $c2, $std_Duration, $util_Util }) {
return $obj;
}
async handle() {
- {((cond) => {if (!cond) throw new Error("assertion failed: c1.peek() == 0")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $c1.peek()),0)))};
- {((cond) => {if (!cond) throw new Error("assertion failed: c2.peek() == 0")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $c2.peek()),0)))};
+ const c1val = (await $c1.peek());
+ const c2val = (await $c2.peek());
(await $util_Util.sleep((await $std_Duration.fromSeconds(66))));
- {((cond) => {if (!cond) throw new Error("assertion failed: c1.peek() >= 1")})(((await $c1.peek()) >= 1))};
- {((cond) => {if (!cond) throw new Error("assertion failed: c2.peek() >= 1")})(((await $c2.peek()) >= 1))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: c1.peek() >= c1val + 1")})(((await $c1.peek()) >= (c1val + 1)))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: c2.peek() >= c2val + 1")})(((await $c2.peek()) >= (c2val + 1)))};
}
}
return $Closure3;
@@ -508,7 +508,7 @@ class $Root extends $stdlib.std.Resource {
const c2 = this.node.root.newAbstract("@winglang/sdk.cloud.Counter",this,"c2");
(from_cron.onTick(new $Closure1(this,"$Closure1")));
(from_rate.onTick(new $Closure2(this,"$Closure2")));
- this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"on tick is called both for rate and cron schedules",new $Closure3(this,"$Closure3"),({"timeout": (std.Duration.fromSeconds(120))}));
+ this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"on tick is called both for rate and cron schedules",new $Closure3(this,"$Closure3"),{ timeout: (std.Duration.fromSeconds(120)) });
}
}
const $App = $stdlib.core.App.for(process.env.WING_TARGET);
diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/table/get.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/table/get.test.w_compile_tf-aws.md
index 1417ffc8f1e..646e9724e18 100644
--- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/table/get.test.w_compile_tf-aws.md
+++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/table/get.test.w_compile_tf-aws.md
@@ -23,7 +23,7 @@ module.exports = function({ $table }) {
}
catch ($error_actual) {
const actual = $error_actual.message;
- {((cond) => {if (!cond) throw new Error("assertion failed: actual == expected")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(actual,expected)))};
+ {((cond) => {if (!cond) throw new Error("assertion failed: actual.contains(expected)")})(actual.includes(expected))};
error = true;
}
{((cond) => {if (!cond) throw new Error("assertion failed: error")})(error)};
diff --git a/tools/hangar/__snapshots__/test_corpus/valid/redis.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/redis.test.w_compile_tf-aws.md
index a6af688d70b..6dc9ca346c8 100644
--- a/tools/hangar/__snapshots__/test_corpus/valid/redis.test.w_compile_tf-aws.md
+++ b/tools/hangar/__snapshots__/test_corpus/valid/redis.test.w_compile_tf-aws.md
@@ -30,10 +30,6 @@ module.exports = function({ $queue, $r, $r2, $util_Util }) {
return $obj;
}
async handle() {
- const connection = (await $r.rawClient());
- (await connection.set("wing","does redis"));
- const value = (await connection.get("wing"));
- {((cond) => {if (!cond) throw new Error("assertion failed: value == \"does redis\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(value,"does redis")))};
(await $r2.set("wing","does redis again"));
const value2 = (await $r2.get("wing"));
{((cond) => {if (!cond) throw new Error("assertion failed: value2 == \"does redis again\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(value2,"does redis again")))};
@@ -623,7 +619,7 @@ class $Root extends $stdlib.std.Resource {
_registerBind(host, ops) {
if (ops.includes("handle")) {
$Closure2._registerBindObject(queue, host, ["push"]);
- $Closure2._registerBindObject(r, host, ["get", "rawClient"]);
+ $Closure2._registerBindObject(r, host, ["get"]);
$Closure2._registerBindObject(r2, host, ["get", "set"]);
}
super._registerBind(host, ops);