-
-
Notifications
You must be signed in to change notification settings - Fork 160
/
Stage.spec.ts
226 lines (177 loc) · 8.49 KB
/
Stage.spec.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
import 'mocha';
import * as sinon from 'sinon';
import { ConfigurationError, LogicError } from '../../src/errors';
import { Actor, Interaction } from '../../src/screenplay';
import { DressingRoom, Stage, StageManager } from '../../src/stage';
import { expect } from '../expect';
describe('Stage', () => {
class Extras implements DressingRoom {
prepare(actor: Actor): Actor {
return actor;
}
}
const stageManager = sinon.createStubInstance(StageManager);
/**
* @test {Stage#actor}
* @test {Stage#theActorCalled}
*/
it('provides both the more verbose and more concise way of accessing the actors', () => {
const
name = 'Alice',
actors = new Extras(),
stage = new Stage(actors, stageManager as unknown as StageManager);
expect(stage.actor(name)).to.equal(stage.theActorCalled(name));
});
describe('when instantiating actors', () => {
/** @test {Stage#actor} */
it('instantiates a new actor when their name is called for the first time', () => {
const
name = 'Alice',
actors = new Extras(),
stage = new Stage(actors, stageManager as unknown as StageManager);
sinon.spy(actors, 'prepare');
const actor = stage.actor(name);
expect((actors.prepare as any).getCall(0).args[0].name).to.equal(name);
expect(actor.name).to.equal('Alice');
});
/** @test {Stage#actor} */
it('returns an existing actor if it has already been instantiated before', () => {
const
name = 'Alice',
actors = new Extras(),
stage = new Stage(actors, stageManager as unknown as StageManager);
sinon.spy(actors, 'prepare');
const a1 = stage.actor(name);
const a2 = stage.actor(name);
expect((actors.prepare as any).getCall(0).args[0].name).to.equal(name);
expect(actors.prepare).to.have.been.calledOnce; // tslint:disable-line:no-unused-expression
expect(a1).to.equal(a2);
});
});
describe('when referencing a recently retrieved actor', () => {
/** @test {Stage#actor} */
it('retrieves the current actor, if there is any', () => {
const
name = 'Alice',
stage = new Stage(new Extras(), stageManager as unknown as StageManager);
const a1 = stage.actor(name);
const a2 = stage.theActorInTheSpotlight();
expect(a2).to.equal(a1);
});
/**
* @test {Stage#theActorInTheSpotlight}
* @test {Stage#theActorInTheSpotlight}
*/
it('provides both the more verbose and more concise way of accessing the actors in the spotlight', () => {
const
name = 'Alice',
stage = new Stage(new Extras(), stageManager as unknown as StageManager);
const a1 = stage.actor(name);
const a2 = stage.theActorCalled(name);
const a3 = stage.theActorInTheSpotlight();
expect(a1).to.equal(a2);
expect(a1).to.equal(a3);
});
/**
* @test {Stage#theActorInTheSpotlight}
* @test {Stage#theActorInTheSpotlight}
*/
it('complains if you try to access the actor in the spotlight, but there isn\'t any yet', () => {
const
stage = new Stage(new Extras(), stageManager as unknown as StageManager);
expect(
() => stage.theActorInTheSpotlight(),
).to.throw(LogicError, `There is no actor in the spotlight yet. Make sure you instantiate one with stage.actor(actorName) before calling this method.`);
});
});
describe('when correlating activities', () => {
const SomeActivity = () => Interaction.where(`#actor doesn't do much`, actor => void 0);
it('provides ActivityDetails for a given Activity', () => {
const
actors = new Extras(),
stage = new Stage(actors, stageManager as unknown as StageManager);
const details = stage.activityDetailsFor(SomeActivity(), stage.actor('Alice'));
expect(details.name.value).to.equal(`Alice doesn't do much`);
expect(details.correlationId.value).to.be.a('string'); // tslint:disable-line:no-unused-expression
});
it('allows for the recently ActivityDetails to be retrieved', () => {
const
actors = new Extras(),
stage = new Stage(actors, stageManager as unknown as StageManager);
const details = stage.activityDetailsFor(SomeActivity(), stage.actor('Alice'));
expect(stage.currentActivityDetails()).to.equal(details);
});
it('complains if ActivityDetails attempted to be retrieved before they have been generated', () => {
const
actors = new Extras(),
stage = new Stage(actors, stageManager as unknown as StageManager);
expect(() => stage.currentActivityDetails()).to.throw(LogicError, 'No activity is being performed. Did you call activityDetailsFor before invoking currentActivityDetails?');
});
});
describe('when an error occurs', () => {
it('complains when instantiated with no DressingRoom', () => {
expect(() => {
const stage = new Stage(null, stageManager as unknown as StageManager);
}).to.throw(Error, 'DressingRoom should be defined');
});
it('complains when instantiated with no StageManager', () => {
expect(() => {
const stage = new Stage(new Extras(), null);
}).to.throw(Error, 'StageManager should be defined');
});
/** @test {Stage#actor} */
it('complains if the DressingRoom does not provide a way to instantiate a given actor', () => {
const
name = 'Alice',
actors: DressingRoom = {
prepare: (actor: Actor) => undefined,
},
stage = new Stage(actors, stageManager as unknown as StageManager);
expect(() => {
stage.actor(name);
}).to.throw(ConfigurationError, `Instead of a new instance of actor "${ name }", DressingRoom returned undefined`);
});
/** @test {Stage#actor} */
it('complains if the DressingRoom does not provide a way to prepare a given actor and mentions the type of the DressingRoom, when available', () => {
class AwesomeActors implements DressingRoom {
prepare(actor: Actor): Actor {
return undefined;
}
}
const
name = 'Alice',
actors = new AwesomeActors(),
stage = new Stage(actors, stageManager as unknown as StageManager);
expect(() => {
stage.actor(name);
}).to.throw(ConfigurationError, `Instead of a new instance of actor "${ name }", AwesomeActors returned undefined`);
});
/** @test {Stage#actor} */
it('complains if the DressingRoom throws an error during actor instantiation', () => {
const
name = 'Alice',
actors: DressingRoom = {
prepare: (actor: Actor) => { throw new Error(`I'm not working today`); },
},
stage = new Stage(actors, stageManager as unknown as StageManager);
expect(() => {
stage.actor(name);
}).to.throw(ConfigurationError, `DressingRoom encountered a problem when preparing actor "${ name }" for stage`);
});
/** @test {Stage#actor} */
it('complains if the DressingRoom throws an error during actor instantiation and mentions the type of the DressingRoom, when available', () => {
class MoodyActors implements DressingRoom {
prepare(actor: Actor): Actor {
throw new Error(`I'm not working today`);
}
}
const
name = 'Alice',
actors = new MoodyActors(),
stage = new Stage(actors, stageManager as unknown as StageManager);
expect(() => {
stage.actor(name);
}).to.throw(ConfigurationError, `MoodyActors encountered a problem when preparing actor "${ name }" for stage`);
});
});
});