From 0c45461be67c8a6f0b84e06b62889f972dd1cfb6 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:31:58 -0500 Subject: [PATCH] test(cli): Add demo section tests, excluding familiar-chat --- packages/cli/test/demo/confined-script.js | 9 +++ packages/cli/test/demo/counter-example.js | 60 ++++++++++++++++ packages/cli/test/demo/doubler-agent.js | 52 ++++++++++++++ packages/cli/test/demo/index.test.js | 69 +++++++++++++++++++ .../cli/test/demo/mailboxes-are-symmetric.js | 14 ++++ packages/cli/test/demo/names-in-transit.js | 27 ++++++++ packages/cli/test/demo/sending-messages.js | 29 ++++++++ 7 files changed, 260 insertions(+) create mode 100644 packages/cli/test/demo/confined-script.js create mode 100644 packages/cli/test/demo/counter-example.js create mode 100644 packages/cli/test/demo/doubler-agent.js create mode 100644 packages/cli/test/demo/mailboxes-are-symmetric.js create mode 100644 packages/cli/test/demo/names-in-transit.js create mode 100644 packages/cli/test/demo/sending-messages.js diff --git a/packages/cli/test/demo/confined-script.js b/packages/cli/test/demo/confined-script.js new file mode 100644 index 0000000000..e8ce912edf --- /dev/null +++ b/packages/cli/test/demo/confined-script.js @@ -0,0 +1,9 @@ +/** @import {TestRoutine} from '../types */ + +/** @type {TestRoutine} */ +export const section = async (execa, testLine) => { + // If a runlet returns a promise for some value, it will print that value before exiting gracefully. + await testLine(execa`endo run runlet.js a b c`, { + stdout: "Hello, World! [ 'a', 'b', 'c' ]\n42", + }); +}; diff --git a/packages/cli/test/demo/counter-example.js b/packages/cli/test/demo/counter-example.js new file mode 100644 index 0000000000..74cbfd42d2 --- /dev/null +++ b/packages/cli/test/demo/counter-example.js @@ -0,0 +1,60 @@ +/** @import {Context, TestRoutine} from '../types' */ + +/** @type {TestRoutine} */ +export const section = async (execa, testLine) => { + // We can create an instance of the counter and give it a name. + await testLine(execa`endo make counter.js --name counter`, { + stdout: 'Object [Alleged: Counter] {}', + }); + + // Then, we can send messages to the counter and see their responses... + await testLine(execa`endo eval E(counter).incr() counter`, { + stdout: '1', + }); + await testLine(execa`endo eval E(counter).incr() counter`, { + stdout: '2', + }); + await testLine(execa`endo eval E(counter).incr() counter`, { + stdout: '3', + }); + + // Aside: in all the above cases, we use counter both as the property name... + await testLine(execa`endo eval E(c).incr() c:counter`, { + stdout: '4', + }); + + // Endo preserves the commands that led to the creation of the counter value... + await testLine(execa`endo restart`); + await testLine(execa`endo eval E(counter).incr() counter`, { + stdout: '1', + }); + await testLine(execa`endo eval E(counter).incr() counter`, { + stdout: '2', + }); + await testLine(execa`endo eval E(counter).incr() counter`, { + stdout: '3', + }); + + // Aside, since Eventual Send, the machinery under the E operator... + await testLine(execa`endo spawn greeter`); + await testLine( + execa`endo eval --worker greeter '${'Hello, World!'}' --name greeting`, + { + stdout: 'Hello, World!', + }, + ); + await testLine(execa`endo show greeting`, { + stdout: 'Hello, World!', + }); +}; + +/** @type {Context} */ +export const context = { + setup: async execa => { + await execa`endo make counter.js --name counter`; + await execa`endo eval E(counter).incr() counter`; + await execa`endo eval E(counter).incr() counter`; + await execa`endo eval E(counter).incr() counter`; + await execa`endo spawn greeter`; + }, +}; diff --git a/packages/cli/test/demo/doubler-agent.js b/packages/cli/test/demo/doubler-agent.js new file mode 100644 index 0000000000..b0faffc561 --- /dev/null +++ b/packages/cli/test/demo/doubler-agent.js @@ -0,0 +1,52 @@ +/** @import {Context, TestRoutine} from '../types' */ + +/** @type {TestRoutine} */ +export const section = async (execa, testLine) => { + // We make a doubler mostly the same way we made the counter... + await testLine(execa`endo mkguest doubler-handle doubler-agent`, { + stdout: 'Object [Alleged: EndoGuest] {}', + }); + await testLine( + execa`endo make doubler.js --name doubler --powers doubler-agent`, + ); + + // This creates a doubler, but the doubler cannot respond until we resolve... + await testLine(execa`endo inbox`, { + stdout: + /^0\. "doubler-handle" requested "a counter, suitable for doubling"/, + }); + await testLine(execa`endo resolve 0 counter`); + + // Now we can get a response from the doubler. + await testLine(execa`endo eval E(doubler).incr() doubler`, { + stdout: '8', + }); + await testLine(execa`endo eval E(doubler).incr() doubler`, { + stdout: '10', + }); + await testLine(execa`endo eval E(doubler).incr() doubler`, { + stdout: '12', + }); + + // Also, in the optional second argument to request, doubler.js names... + await testLine(execa`endo restart`); + await testLine(execa`endo eval E(doubler).incr() doubler`, { + stdout: '2', + }); + await testLine(execa`endo eval E(doubler).incr() doubler`, { + stdout: '4', + }); + await testLine(execa`endo eval E(doubler).incr() doubler`, { + stdout: '6', + }); +}; + +/** @type {Context} */ +export const context = { + setup: async execa => { + await execa`endo mkguest doubler-handle doubler-agent`; + await execa`endo make doubler.js --name doubler --powers doubler-agent`; + await execa`endo inbox`; + await execa`endo resolve 0 counter`; + }, +}; diff --git a/packages/cli/test/demo/index.test.js b/packages/cli/test/demo/index.test.js index 67e50ef1e1..a531c7a99c 100644 --- a/packages/cli/test/demo/index.test.js +++ b/packages/cli/test/demo/index.test.js @@ -3,6 +3,12 @@ import { $ } from 'execa'; import { makeSectionTest } from '../section.js'; import { withContext } from '../with-context.js'; import { daemonContext } from '../daemon-context.js'; +import * as counterExample from './counter-example.js'; +import * as doublerAgent from './doubler-agent.js'; +import * as confinedScript from './confined-script.js'; +import * as sendingMessages from './sending-messages.js'; +import * as namesInTransit from './names-in-transit.js'; +import * as mailboxesAreSymmetric from './mailboxes-are-symmetric.js'; test.serial( 'trivial', @@ -14,3 +20,66 @@ test.serial( }), ), ); + +test.serial( + 'counter-example', + makeSectionTest( + $({ cwd: 'demo' }), + withContext(daemonContext)(counterExample.section), + ), +); + +test.serial( + 'doubler-agent', + makeSectionTest( + $({ cwd: 'demo' }), + withContext(daemonContext, counterExample.context)(doublerAgent.section), + ), +); + +test.serial.failing( + 'sending-messages', + makeSectionTest( + $({ cwd: 'demo' }), + withContext( + daemonContext, + counterExample.context, + doublerAgent.context, + )(sendingMessages.section), + ), +); + +test.serial.failing( + 'names-in-transit', + makeSectionTest( + $({ cwd: 'demo' }), + withContext( + daemonContext, + counterExample.context, + doublerAgent.context, + sendingMessages.context, + )(namesInTransit.section), + ), +); + +test.serial.failing( + 'mailboxes-are-symmetric', + makeSectionTest( + $({ cwd: 'demo' }), + withContext( + daemonContext, + counterExample.context, + doublerAgent.context, + sendingMessages.context, + namesInTransit.context, + )(mailboxesAreSymmetric.section), + ), +); + +test.serial( + 'confined-script', + makeSectionTest( + $({ cwd: 'demo' }), + withContext(daemonContext)(confinedScript.section), + ), +); diff --git a/packages/cli/test/demo/mailboxes-are-symmetric.js b/packages/cli/test/demo/mailboxes-are-symmetric.js new file mode 100644 index 0000000000..342d1bf2df --- /dev/null +++ b/packages/cli/test/demo/mailboxes-are-symmetric.js @@ -0,0 +1,14 @@ +/** @import {TestRoutine} from '../types' */ + +/** @type {TestRoutine} */ +export const section = async (execa, testLine) => { + // Guests can also send their host messages... + await testLine( + execa`endo send HOST --as alice-agent ${'This is the @doubler you sent me.'}`, + ); + await testLine(execa`endo inbox`, { + stdout: /^0\. "alice" sent "This is the @doubler you sent me\."/, + }); + await testLine(execa`endo adopt 0 doubler doubler-from-alice`); + await testLine(execa`endo dismiss 0`); +}; diff --git a/packages/cli/test/demo/names-in-transit.js b/packages/cli/test/demo/names-in-transit.js new file mode 100644 index 0000000000..6f711a312d --- /dev/null +++ b/packages/cli/test/demo/names-in-transit.js @@ -0,0 +1,27 @@ +/** @import {Context, TestRoutine} from '../types' */ + +/** @type {TestRoutine} */ +export const section = async (execa, testLine) => { + // In this example, we send alice our "doubler" but let it appear... + await testLine( + execa`endo send alice ${'Please enjoy this @counter:doubler.'}`, + ); + await testLine(execa`endo inbox --as alice-agent`, { + stdout: /^1\. "HOST" sent "Please enjoy this @counter\."/, + }); + await testLine(execa`endo adopt --as alice-agent 1 counter --name redoubler`); + await testLine(execa`endo list --as alice-agent`, { + stdout: 'redoubler', + }); + await testLine(execa`endo dismiss --as alice-agent 1`); +}; + +/** @type {Context} */ +export const context = { + setup: async execa => { + await execa`endo send alice ${'Please enjoy this @counter:doubler.'}`; + await execa`endo inbox --as alice-agent`; + await execa`endo adopt --as alice-agent 1 counter --name redoubler`; + await execa`endo dismiss --as alice-agent 1`; + }, +}; diff --git a/packages/cli/test/demo/sending-messages.js b/packages/cli/test/demo/sending-messages.js new file mode 100644 index 0000000000..320ba9ccf9 --- /dev/null +++ b/packages/cli/test/demo/sending-messages.js @@ -0,0 +1,29 @@ +/** @import {Context, TestRoutine} from '../types' */ + +/** @type {TestRoutine} */ +export const section = async (execa, testLine) => { + // So far, we have run guest programs like the doubler. Guests and hosts can exchange messages... + await testLine(execa`endo mkguest alice alice-agent`, { + stdout: 'Object [Alleged: EndoGuest] {}', + }); + await testLine(execa`endo send alice ${'Please enjoy this @doubler.'}`); + await testLine(execa`endo inbox --as alice-agent`, { + stdout: /^0\. "HOST" sent "Please enjoy this @doubler\."/, + }); + await testLine(execa`endo adopt --as alice-agent 0 doubler`); + await testLine(execa`endo list --as alice-agent`, { + stdout: 'doubler', + }); + await testLine(execa`endo dismiss --as alice-agent 0`); +}; + +/** @type {Context} */ +export const context = { + setup: async execa => { + await execa`endo mkguest alice alice-agent`; + await execa`endo send alice ${'Please enjoy this @doubler.'}`; + // await execa`endo adopt --as alice-agent 0 doubler`; + await execa`endo adopt alice-agent 0 doubler`; + await execa`endo dismiss --as alice-agent 0`; + }, +};