Skip to content

Commit 9499c52

Browse files
authored
Merge pull request #96 from thefrontside/multi-test-adapter
🐛 run more than one test
2 parents 77bc938 + 3e12505 commit 9499c52

File tree

4 files changed

+134
-53
lines changed

4 files changed

+134
-53
lines changed

test-adapter/box.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Err, Ok, type Operation, type Result } from "effection";
2+
3+
export function* box<T>(content: () => Operation<T>): Operation<Result<T>> {
4+
try {
5+
return Ok(yield* content());
6+
} catch (error) {
7+
return Err(error as Error);
8+
}
9+
}
10+
11+
export function unbox<T>(result: Result<T>): T {
12+
if (result.ok) {
13+
return result.value;
14+
}
15+
throw result.error;
16+
}

test-adapter/deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@effectionx/test-adapter",
3-
"version": "0.5.0",
3+
"version": "0.5.1",
44
"license": "MIT",
55
"exports": "./mod.ts",
66
"imports": {

test-adapter/mod.ts

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
1-
import type { Future, Operation, Result, Scope } from "effection";
2-
import { Err, Ok, run, suspend, useScope, withResolvers } from "effection";
1+
import type {
2+
Future,
3+
Operation,
4+
Result,
5+
Scope,
6+
WithResolvers,
7+
} from "effection";
8+
import {
9+
createScope,
10+
Ok,
11+
run,
12+
suspend,
13+
useScope,
14+
withResolvers,
15+
} from "effection";
16+
import { box } from "./box.ts";
317

418
export interface TestOperation {
519
(): Operation<void>;
@@ -63,7 +77,7 @@ export interface TestAdapter {
6377
*
6478
* @ignore
6579
*/
66-
["@@init@@"](): Operation<Scope>;
80+
["@@init@@"](): Operation<Result<Scope>>;
6781
}
6882

6983
export interface TestAdapterOptions {
@@ -100,7 +114,8 @@ export function createTestAdapter(
100114
};
101115
const { parent, name = anonymousNames.next().value } = options;
102116

103-
let scope: Scope | undefined = undefined;
117+
let scope: WithResolvers<Result<Scope>> | undefined = undefined;
118+
let destroy: () => Operation<void> = function* () {};
104119

105120
const adapter: TestAdapter = {
106121
parent,
@@ -123,63 +138,65 @@ export function createTestAdapter(
123138
setup.all.push(op);
124139
},
125140
runTest(op) {
126-
return run(() =>
127-
box(function* () {
128-
const setups = adapter.lineage.reduce(
129-
(all, adapter) => all.concat(adapter.setup.each),
130-
[] as TestOperation[],
131-
);
132-
133-
let scope = yield* adapter["@@init@@"]();
134-
135-
let test = yield* scope.spawn(function* () {
136-
for (const setup of setups) {
137-
yield* setup();
141+
return run(function* () {
142+
let init = yield* adapter["@@init@@"]();
143+
if (!init.ok) {
144+
return init;
145+
}
146+
let scope = init.value;
147+
148+
const setups = adapter.lineage.reduce(
149+
(all, adapter) => all.concat(adapter.setup.each),
150+
[] as TestOperation[],
151+
);
152+
153+
let test = yield* scope.spawn(() =>
154+
box(function* () {
155+
for (let fn of setups) {
156+
yield* fn();
138157
}
139158
yield* op();
140-
});
141-
142-
yield* test;
143-
}())
144-
);
159+
})
160+
);
161+
return yield* test;
162+
});
145163
},
146164

147-
// no-op that will be replaced once initialze
148-
destroy: () => run(function* () {}),
149-
150165
*["@@init@@"]() {
151166
if (scope) {
152-
return scope;
167+
return yield* scope.operation;
153168
}
169+
scope = withResolvers<Result<Scope>>();
154170

155-
let parentScope = parent
156-
? yield* parent["@@init@@"]()
157-
: yield* useScope();
171+
let parent = adapter.parent
172+
? yield* adapter.parent["@@init@@"]()
173+
: Ok(createScope()[0]);
158174

159-
let initialized = withResolvers<Scope>();
175+
if (!parent.ok) {
176+
scope.resolve(parent);
177+
return yield* scope.operation;
178+
}
160179

161-
let task = yield* parentScope.spawn(function* () {
162-
scope = yield* useScope();
163-
for (let op of setup.all) {
164-
yield* op();
180+
let task = yield* parent.value.spawn(function* () {
181+
let init = yield* box(function* () {
182+
for (let initializer of adapter.setup.all) {
183+
yield* initializer();
184+
}
185+
});
186+
if (!init.ok) {
187+
scope!.resolve(init);
188+
} else {
189+
scope!.resolve(Ok(yield* useScope()));
190+
yield* suspend();
165191
}
166-
initialized.resolve(scope);
167-
yield* suspend();
168192
});
169193

170-
adapter.destroy = () => run(task.halt);
194+
destroy = task.halt;
171195

172-
return yield* initialized.operation;
196+
return yield* scope.operation;
173197
},
198+
destroy: () => run(destroy),
174199
};
175200

176201
return adapter;
177202
}
178-
179-
function* box<T>(op: Operation<T>): Operation<Result<T>> {
180-
try {
181-
return Ok(yield* op);
182-
} catch (error) {
183-
return Err(error as Error);
184-
}
185-
}

test-adapter/test/adapter.test.ts

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,14 @@ describe("TestAdapter", () => {
5555
});
5656

5757
grandparent.addSetup(function* () {
58-
sequence.push("grandparent/setup:each");
58+
yield* resource<void>(function* (provide) {
59+
try {
60+
sequence.push("grandparent/setup:each");
61+
yield* provide();
62+
} finally {
63+
sequence.push("grandparent/teardown:each");
64+
}
65+
});
5966
});
6067

6168
let parent = createTestAdapter({ name: "parent", parent: grandparent });
@@ -72,24 +79,65 @@ describe("TestAdapter", () => {
7279
})
7380
);
7481

75-
let child = createTestAdapter({ name: "child", parent });
82+
parent.addSetup(() =>
83+
resource(function* (provide) {
84+
try {
85+
sequence.push("parent/setup:each");
86+
yield* provide();
87+
} finally {
88+
sequence.push("parent/teardown:each");
89+
}
90+
})
91+
);
7692

77-
await child.runTest(function* () {
78-
sequence.push("child/run");
79-
contexts["child"] = yield* context.expect();
93+
let first = createTestAdapter({ name: "child", parent });
94+
95+
let result = await first.runTest(function* () {
96+
sequence.push("first-child/run");
97+
contexts["first-child/run"] = yield* context.expect();
98+
});
99+
100+
if (!result.ok) {
101+
throw result.error;
102+
}
103+
104+
let second = createTestAdapter({ name: "child", parent });
105+
106+
result = await second.runTest(function* () {
107+
sequence.push("second-child/run");
108+
contexts["second-child/run"] = yield* context.expect();
80109
});
81110

111+
if (!result.ok) {
112+
throw result.error;
113+
}
114+
82115
await grandparent.destroy();
83116

84117
expect(sequence).toEqual([
85118
"grandparent/setup:once",
86119
"parent/setup:once",
87120
"grandparent/setup:each",
88-
"child/run",
121+
"parent/setup:each",
122+
"first-child/run",
123+
"parent/teardown:each",
124+
"grandparent/teardown:each",
125+
"grandparent/setup:each",
126+
"parent/setup:each",
127+
"second-child/run",
128+
"parent/teardown:each",
129+
"grandparent/teardown:each",
89130
"parent/teardown:once",
90131
"grandparent/teardown:once",
91132
]);
92133

93-
expect(contexts).toEqual({ parent: "initialized", child: "initialized" });
134+
expect(contexts).toEqual({
135+
parent: "initialized",
136+
"first-child/run": "initialized",
137+
"second-child/run": "initialized",
138+
});
139+
});
140+
141+
it("can run multiple tests", async () => {
94142
});
95143
});

0 commit comments

Comments
 (0)