@things-factory/worklist 9.1.19 → 10.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/components/activity-thread-timeline.d.ts +1 -9
- package/dist-client/components/activity-thread-timeline.js +1 -3
- package/dist-client/components/activity-thread-timeline.js.map +1 -1
- package/dist-client/pages/activity/activity-list-page.d.ts +1 -7
- package/dist-client/pages/activity/activity-list-page.js +125 -234
- package/dist-client/pages/activity/activity-list-page.js.map +1 -1
- package/dist-client/pages/activity/activity-page.d.ts +1 -7
- package/dist-client/pages/activity/activity-page.js +51 -93
- package/dist-client/pages/activity/activity-page.js.map +1 -1
- package/dist-client/pages/activity/starter-list-page.d.ts +1 -7
- package/dist-client/pages/activity/starter-list-page.js +33 -62
- package/dist-client/pages/activity/starter-list-page.js.map +1 -1
- package/dist-client/pages/activity-approval/activity-approval-list-page.d.ts +1 -7
- package/dist-client/pages/activity-approval/activity-approval-list-page.js +50 -95
- package/dist-client/pages/activity-approval/activity-approval-list-page.js.map +1 -1
- package/dist-client/pages/activity-approval/activity-approval-page.d.ts +1 -7
- package/dist-client/pages/activity-approval/activity-approval-page.js +73 -119
- package/dist-client/pages/activity-approval/activity-approval-page.js.map +1 -1
- package/dist-client/pages/activity-instance/activity-instance-list-page.d.ts +0 -6
- package/dist-client/pages/activity-instance/activity-instance-list-page.js +63 -120
- package/dist-client/pages/activity-instance/activity-instance-list-page.js.map +1 -1
- package/dist-client/pages/activity-instance/activity-instance-search-page.d.ts +1 -7
- package/dist-client/pages/activity-instance/activity-instance-search-page.js +55 -101
- package/dist-client/pages/activity-instance/activity-instance-search-page.js.map +1 -1
- package/dist-client/pages/activity-instance/activity-instance-start-page.d.ts +1 -7
- package/dist-client/pages/activity-instance/activity-instance-start-page.js +65 -109
- package/dist-client/pages/activity-instance/activity-instance-start-page.js.map +1 -1
- package/dist-client/pages/activity-stats/activity-stats-list-page.d.ts +1 -7
- package/dist-client/pages/activity-stats/activity-stats-list-page.js +50 -95
- package/dist-client/pages/activity-stats/activity-stats-list-page.js.map +1 -1
- package/dist-client/pages/activity-store/activity-store-page.d.ts +1 -7
- package/dist-client/pages/activity-store/activity-store-page.js +2 -3
- package/dist-client/pages/activity-store/activity-store-page.js.map +1 -1
- package/dist-client/pages/activity-supervisor/reporter-list-page.d.ts +1 -7
- package/dist-client/pages/activity-supervisor/reporter-list-page.js +36 -66
- package/dist-client/pages/activity-supervisor/reporter-list-page.js.map +1 -1
- package/dist-client/pages/activity-template/activity-template-list-page.d.ts +1 -7
- package/dist-client/pages/activity-template/activity-template-list-page.js +70 -134
- package/dist-client/pages/activity-template/activity-template-list-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-list-page.d.ts +1 -7
- package/dist-client/pages/activity-thread/activity-thread-list-page.js +49 -93
- package/dist-client/pages/activity-thread/activity-thread-list-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.d.ts +1 -7
- package/dist-client/pages/activity-thread/activity-thread-page.js +80 -135
- package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view-page.d.ts +1 -7
- package/dist-client/pages/activity-thread/activity-thread-view-page.js +54 -80
- package/dist-client/pages/activity-thread/activity-thread-view-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view.js +4 -0
- package/dist-client/pages/activity-thread/activity-thread-view.js.map +1 -1
- package/dist-client/pages/dashboard/dashboard-home.js +3 -5
- package/dist-client/pages/dashboard/dashboard-home.js.map +1 -1
- package/dist-client/pages/installable-activity/installable-activity-list-page.d.ts +0 -6
- package/dist-client/pages/installable-activity/installable-activity-list-page.js +68 -130
- package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -1
- package/dist-client/pages/todo/approval-done-list-page.d.ts +1 -7
- package/dist-client/pages/todo/approval-done-list-page.js +53 -100
- package/dist-client/pages/todo/approval-done-list-page.js.map +1 -1
- package/dist-client/pages/todo/approval-pending-list-page.d.ts +0 -6
- package/dist-client/pages/todo/approval-pending-list-page.js +63 -119
- package/dist-client/pages/todo/approval-pending-list-page.js.map +1 -1
- package/dist-client/pages/todo/done-list-calendar-page.d.ts +1 -7
- package/dist-client/pages/todo/done-list-calendar-page.js +2 -3
- package/dist-client/pages/todo/done-list-calendar-page.js.map +1 -1
- package/dist-client/pages/todo/done-list-page.d.ts +1 -7
- package/dist-client/pages/todo/done-list-page.js +56 -106
- package/dist-client/pages/todo/done-list-page.js.map +1 -1
- package/dist-client/pages/todo/draft-list-page.d.ts +1 -7
- package/dist-client/pages/todo/draft-list-page.js +49 -88
- package/dist-client/pages/todo/draft-list-page.js.map +1 -1
- package/dist-client/pages/todo/pickable-list-page.d.ts +1 -7
- package/dist-client/pages/todo/pickable-list-page.js +48 -91
- package/dist-client/pages/todo/pickable-list-page.js.map +1 -1
- package/dist-client/pages/todo/todo-list-page.d.ts +0 -6
- package/dist-client/pages/todo/todo-list-page.js +56 -106
- package/dist-client/pages/todo/todo-list-page.js.map +1 -1
- package/dist-client/pages/worklist-home.js +2 -3
- package/dist-client/pages/worklist-home.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/templates/activity-approval-context-template.js +8 -12
- package/dist-client/templates/activity-approval-context-template.js.map +1 -1
- package/dist-client/templates/activity-instance-context-template.js +8 -12
- package/dist-client/templates/activity-instance-context-template.js.map +1 -1
- package/dist-client/templates/activity-thread-context-template.js +8 -12
- package/dist-client/templates/activity-thread-context-template.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/activity-approval/approve.js +2 -2
- package/dist-server/controllers/activity-approval/approve.js.map +1 -1
- package/dist-server/controllers/activity-thread/submit.js +2 -2
- package/dist-server/controllers/activity-thread/submit.js.map +1 -1
- package/dist-server/service/index.d.ts +2 -2
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -16
- package/spec/integration/approval-mixed-types.spec.ts +491 -0
- package/spec/integration/approval-role-based.spec.ts +389 -0
- package/spec/integration/instance-lifecycle.spec.ts +406 -0
- package/spec/integration/role-approval-edge-cases.spec.ts +581 -0
- package/spec/unit/controllers/activity-instance-issue.spec.ts +360 -0
- package/spec/unit/controllers/activity-thread-submit.spec.ts +384 -0
- package/spec/unit/role-approval-escalate-logic.spec.ts +499 -0
- package/spec/unit/role-approval-submit-logic.spec.ts +481 -0
- package/spec/unit/thread-state-helpers.spec.ts +253 -0
- package/translations/en.json +1 -1
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActivityThread Submit Controller Tests
|
|
3
|
+
* ActivityThread 제출 컨트롤러 테스트
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { TestDatabase } from '../../../../../test/test-database'
|
|
7
|
+
import { withTestTransaction } from '../../../../../test/test-context'
|
|
8
|
+
import {
|
|
9
|
+
domainFactory,
|
|
10
|
+
userFactory,
|
|
11
|
+
roleFactory,
|
|
12
|
+
activityInstanceFactory,
|
|
13
|
+
activityThreadFactory,
|
|
14
|
+
activityApprovalFactory
|
|
15
|
+
} from '../../../../../test/factories'
|
|
16
|
+
import {
|
|
17
|
+
ActivityInstanceStatus,
|
|
18
|
+
ActivityThreadStatus,
|
|
19
|
+
ActivityApprovalJudgment
|
|
20
|
+
} from '../../../../../test/entities/schemas'
|
|
21
|
+
|
|
22
|
+
describe('ActivityThread Submit Controller', () => {
|
|
23
|
+
let testDb: TestDatabase
|
|
24
|
+
|
|
25
|
+
beforeAll(async () => {
|
|
26
|
+
testDb = TestDatabase.getInstance()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
describe('Submit 기본 동작', () => {
|
|
30
|
+
it('Started 상태의 Thread를 Submit할 수 있어야 한다', async () => {
|
|
31
|
+
await withTestTransaction(async (context) => {
|
|
32
|
+
const { tx, domain, user } = context.state
|
|
33
|
+
|
|
34
|
+
// Given: Started 상태의 Thread
|
|
35
|
+
const instance = await activityInstanceFactory.createWithActivity(
|
|
36
|
+
{ state: ActivityInstanceStatus.Started },
|
|
37
|
+
undefined,
|
|
38
|
+
domain,
|
|
39
|
+
tx
|
|
40
|
+
)
|
|
41
|
+
const thread = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
42
|
+
{
|
|
43
|
+
state: ActivityThreadStatus.Started,
|
|
44
|
+
startedAt: new Date()
|
|
45
|
+
},
|
|
46
|
+
instance,
|
|
47
|
+
user,
|
|
48
|
+
tx
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
// When: Submit 시뮬레이션
|
|
52
|
+
const output = { action: 'Temperature adjusted to normal range' }
|
|
53
|
+
thread.output = output
|
|
54
|
+
thread.state = ActivityThreadStatus.Ended
|
|
55
|
+
thread.terminatedAt = new Date()
|
|
56
|
+
const submitted = await tx.save('ActivityThread', thread)
|
|
57
|
+
|
|
58
|
+
// Then
|
|
59
|
+
expect(submitted.state).toBe(ActivityThreadStatus.Ended)
|
|
60
|
+
expect(submitted.output).toEqual(output)
|
|
61
|
+
expect(submitted.terminatedAt).toBeDefined()
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('output이 Thread에 저장되어야 한다', async () => {
|
|
66
|
+
await withTestTransaction(async (context) => {
|
|
67
|
+
const { tx, domain, user } = context.state
|
|
68
|
+
|
|
69
|
+
// Given
|
|
70
|
+
const instance = await activityInstanceFactory.createWithActivity(
|
|
71
|
+
{ state: ActivityInstanceStatus.Started },
|
|
72
|
+
undefined,
|
|
73
|
+
domain,
|
|
74
|
+
tx
|
|
75
|
+
)
|
|
76
|
+
const thread = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
77
|
+
{ state: ActivityThreadStatus.Started },
|
|
78
|
+
instance,
|
|
79
|
+
user,
|
|
80
|
+
tx
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
// When
|
|
84
|
+
const output = {
|
|
85
|
+
instruction: 'Adjust temperature',
|
|
86
|
+
result: 'success',
|
|
87
|
+
notes: 'Completed without issues'
|
|
88
|
+
}
|
|
89
|
+
thread.output = output
|
|
90
|
+
const updated = await tx.save('ActivityThread', thread)
|
|
91
|
+
|
|
92
|
+
// Then
|
|
93
|
+
expect(updated.output).toEqual(output)
|
|
94
|
+
expect(updated.output?.result).toBe('success')
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
describe('결재라인 없는 경우', () => {
|
|
100
|
+
it('결재라인이 없으면 바로 Ended 상태가 되어야 한다', async () => {
|
|
101
|
+
await withTestTransaction(async (context) => {
|
|
102
|
+
const { tx, domain, user } = context.state
|
|
103
|
+
|
|
104
|
+
// Given: 결재라인 없는 Instance
|
|
105
|
+
const instance = await activityInstanceFactory.createWithActivity(
|
|
106
|
+
{
|
|
107
|
+
state: ActivityInstanceStatus.Started,
|
|
108
|
+
approvalLine: [] // 빈 결재라인
|
|
109
|
+
},
|
|
110
|
+
undefined,
|
|
111
|
+
domain,
|
|
112
|
+
tx
|
|
113
|
+
)
|
|
114
|
+
const thread = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
115
|
+
{ state: ActivityThreadStatus.Started },
|
|
116
|
+
instance,
|
|
117
|
+
user,
|
|
118
|
+
tx
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
// When: Submit
|
|
122
|
+
thread.state = ActivityThreadStatus.Ended
|
|
123
|
+
thread.terminatedAt = new Date()
|
|
124
|
+
const submitted = await tx.save('ActivityThread', thread)
|
|
125
|
+
|
|
126
|
+
// Then: 바로 Ended
|
|
127
|
+
expect(submitted.state).toBe(ActivityThreadStatus.Ended)
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
describe('결재라인 있는 경우', () => {
|
|
133
|
+
it('결재라인이 있으면 Submitted 상태가 되어야 한다', async () => {
|
|
134
|
+
await withTestTransaction(async (context) => {
|
|
135
|
+
const { tx, domain, user } = context.state
|
|
136
|
+
|
|
137
|
+
// Given: 결재라인 있는 Instance
|
|
138
|
+
const approverRole = await roleFactory.create({ name: 'Approver', domain }, tx)
|
|
139
|
+
const instance = await activityInstanceFactory.createWithActivity(
|
|
140
|
+
{
|
|
141
|
+
state: ActivityInstanceStatus.Started,
|
|
142
|
+
approvalLine: [
|
|
143
|
+
{ type: 'Role', value: approverRole.id, approver: { id: approverRole.id, name: approverRole.name } }
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
undefined,
|
|
147
|
+
domain,
|
|
148
|
+
tx
|
|
149
|
+
)
|
|
150
|
+
const thread = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
151
|
+
{ state: ActivityThreadStatus.Started },
|
|
152
|
+
instance,
|
|
153
|
+
user,
|
|
154
|
+
tx
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
// When: Submit (결재 필요)
|
|
158
|
+
thread.state = ActivityThreadStatus.Submitted
|
|
159
|
+
const submitted = await tx.save('ActivityThread', thread)
|
|
160
|
+
|
|
161
|
+
// Then: Submitted 상태로 대기
|
|
162
|
+
expect(submitted.state).toBe(ActivityThreadStatus.Submitted)
|
|
163
|
+
})
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
it('Submit 시 ActivityApproval이 생성되어야 한다', async () => {
|
|
167
|
+
await withTestTransaction(async (context) => {
|
|
168
|
+
const { tx, domain, user } = context.state
|
|
169
|
+
|
|
170
|
+
// Given
|
|
171
|
+
const approverRole = await roleFactory.create({ name: 'Approver', domain }, tx)
|
|
172
|
+
const instance = await activityInstanceFactory.createWithActivity(
|
|
173
|
+
{
|
|
174
|
+
state: ActivityInstanceStatus.Started,
|
|
175
|
+
approvalLine: [
|
|
176
|
+
{ type: 'Role', value: approverRole.id, approver: { id: approverRole.id, name: approverRole.name } }
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
undefined,
|
|
180
|
+
domain,
|
|
181
|
+
tx
|
|
182
|
+
)
|
|
183
|
+
const thread = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
184
|
+
{ state: ActivityThreadStatus.Started },
|
|
185
|
+
instance,
|
|
186
|
+
user,
|
|
187
|
+
tx
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
// When: Submit 후 Approval 생성 시뮬레이션
|
|
191
|
+
thread.state = ActivityThreadStatus.Submitted
|
|
192
|
+
await tx.save('ActivityThread', thread)
|
|
193
|
+
|
|
194
|
+
const approval = await activityApprovalFactory.createWithRole(
|
|
195
|
+
{
|
|
196
|
+
round: 1,
|
|
197
|
+
order: 1,
|
|
198
|
+
judgment: ActivityApprovalJudgment.Pending
|
|
199
|
+
},
|
|
200
|
+
thread,
|
|
201
|
+
approverRole,
|
|
202
|
+
tx
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
// Then
|
|
206
|
+
expect(approval).toBeDefined()
|
|
207
|
+
expect(approval.judgment).toBe(ActivityApprovalJudgment.Pending)
|
|
208
|
+
expect(approval.approverRole?.id).toBe(approverRole.id)
|
|
209
|
+
})
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
describe('다중 레벨 결재', () => {
|
|
214
|
+
it('첫 번째 결재자에게만 Approval이 생성되어야 한다', async () => {
|
|
215
|
+
await withTestTransaction(async (context) => {
|
|
216
|
+
const { tx, domain, user } = context.state
|
|
217
|
+
|
|
218
|
+
// Given: 2단계 결재라인
|
|
219
|
+
const firstApproverRole = await roleFactory.create({ name: 'Team Lead', domain }, tx)
|
|
220
|
+
const secondApproverRole = await roleFactory.create({ name: 'Manager', domain }, tx)
|
|
221
|
+
|
|
222
|
+
const instance = await activityInstanceFactory.createWithActivity(
|
|
223
|
+
{
|
|
224
|
+
state: ActivityInstanceStatus.Started,
|
|
225
|
+
approvalLine: [
|
|
226
|
+
{ type: 'Role', value: firstApproverRole.id, approver: { id: firstApproverRole.id, name: firstApproverRole.name } },
|
|
227
|
+
{ type: 'Role', value: secondApproverRole.id, approver: { id: secondApproverRole.id, name: secondApproverRole.name } }
|
|
228
|
+
]
|
|
229
|
+
},
|
|
230
|
+
undefined,
|
|
231
|
+
domain,
|
|
232
|
+
tx
|
|
233
|
+
)
|
|
234
|
+
const thread = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
235
|
+
{ state: ActivityThreadStatus.Started },
|
|
236
|
+
instance,
|
|
237
|
+
user,
|
|
238
|
+
tx
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
// When: Submit 시 첫 번째 결재자만 생성
|
|
242
|
+
thread.state = ActivityThreadStatus.Submitted
|
|
243
|
+
await tx.save('ActivityThread', thread)
|
|
244
|
+
|
|
245
|
+
const firstApproval = await activityApprovalFactory.createWithRole(
|
|
246
|
+
{
|
|
247
|
+
round: 1,
|
|
248
|
+
order: 1,
|
|
249
|
+
judgment: ActivityApprovalJudgment.Pending
|
|
250
|
+
},
|
|
251
|
+
thread,
|
|
252
|
+
firstApproverRole,
|
|
253
|
+
tx
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
// Then
|
|
257
|
+
expect(firstApproval.order).toBe(1)
|
|
258
|
+
|
|
259
|
+
// 조회해서 1개만 있는지 확인
|
|
260
|
+
const approvals = await tx.getRepository('ActivityApproval').find({
|
|
261
|
+
where: { activityThread: { id: thread.id } }
|
|
262
|
+
})
|
|
263
|
+
expect(approvals.length).toBe(1)
|
|
264
|
+
})
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
describe('Instance 상태 동기화', () => {
|
|
269
|
+
it('모든 Thread가 Ended되면 Instance도 Ended가 되어야 한다', async () => {
|
|
270
|
+
await withTestTransaction(async (context) => {
|
|
271
|
+
const { tx, domain, user } = context.state
|
|
272
|
+
|
|
273
|
+
// Given: 단일 Thread Instance
|
|
274
|
+
const instance = await activityInstanceFactory.createWithActivity(
|
|
275
|
+
{
|
|
276
|
+
state: ActivityInstanceStatus.Started,
|
|
277
|
+
threadsMin: 1,
|
|
278
|
+
threadsMax: 1
|
|
279
|
+
},
|
|
280
|
+
undefined,
|
|
281
|
+
domain,
|
|
282
|
+
tx
|
|
283
|
+
)
|
|
284
|
+
const thread = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
285
|
+
{ state: ActivityThreadStatus.Started },
|
|
286
|
+
instance,
|
|
287
|
+
user,
|
|
288
|
+
tx
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
// When: Thread Ended
|
|
292
|
+
thread.state = ActivityThreadStatus.Ended
|
|
293
|
+
thread.terminatedAt = new Date()
|
|
294
|
+
await tx.save('ActivityThread', thread)
|
|
295
|
+
|
|
296
|
+
// Instance도 Ended로 업데이트 시뮬레이션
|
|
297
|
+
instance.state = ActivityInstanceStatus.Ended
|
|
298
|
+
instance.terminatedAt = new Date()
|
|
299
|
+
const endedInstance = await tx.save('ActivityInstance', instance)
|
|
300
|
+
|
|
301
|
+
// Then
|
|
302
|
+
expect(endedInstance.state).toBe(ActivityInstanceStatus.Ended)
|
|
303
|
+
})
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
it('일부 Thread만 Ended되면 Instance는 Started 유지되어야 한다', async () => {
|
|
307
|
+
await withTestTransaction(async (context) => {
|
|
308
|
+
const { tx, domain } = context.state
|
|
309
|
+
|
|
310
|
+
// Given: 복수 Thread Instance
|
|
311
|
+
const user1 = await userFactory.create({ name: 'User 1' }, tx)
|
|
312
|
+
const user2 = await userFactory.create({ name: 'User 2' }, tx)
|
|
313
|
+
|
|
314
|
+
const instance = await activityInstanceFactory.createWithActivity(
|
|
315
|
+
{
|
|
316
|
+
state: ActivityInstanceStatus.Started,
|
|
317
|
+
threadsMin: 2,
|
|
318
|
+
threadsMax: 2
|
|
319
|
+
},
|
|
320
|
+
undefined,
|
|
321
|
+
domain,
|
|
322
|
+
tx
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
const thread1 = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
326
|
+
{ state: ActivityThreadStatus.Started },
|
|
327
|
+
instance,
|
|
328
|
+
user1,
|
|
329
|
+
tx
|
|
330
|
+
)
|
|
331
|
+
const thread2 = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
332
|
+
{ state: ActivityThreadStatus.Started },
|
|
333
|
+
instance,
|
|
334
|
+
user2,
|
|
335
|
+
tx
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
// When: thread1만 Ended
|
|
339
|
+
thread1.state = ActivityThreadStatus.Ended
|
|
340
|
+
thread1.terminatedAt = new Date()
|
|
341
|
+
await tx.save('ActivityThread', thread1)
|
|
342
|
+
|
|
343
|
+
// Then: Instance는 아직 Started
|
|
344
|
+
// (thread2가 아직 진행 중)
|
|
345
|
+
expect(instance.state).toBe(ActivityInstanceStatus.Started)
|
|
346
|
+
})
|
|
347
|
+
})
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
describe('Output 집계', () => {
|
|
351
|
+
it('Thread의 output이 Instance의 output으로 집계되어야 한다', async () => {
|
|
352
|
+
await withTestTransaction(async (context) => {
|
|
353
|
+
const { tx, domain, user } = context.state
|
|
354
|
+
|
|
355
|
+
// Given
|
|
356
|
+
const instance = await activityInstanceFactory.createWithActivity(
|
|
357
|
+
{ state: ActivityInstanceStatus.Started },
|
|
358
|
+
undefined,
|
|
359
|
+
domain,
|
|
360
|
+
tx
|
|
361
|
+
)
|
|
362
|
+
const thread = await activityThreadFactory.createWithInstanceAndAssignee(
|
|
363
|
+
{ state: ActivityThreadStatus.Started },
|
|
364
|
+
instance,
|
|
365
|
+
user,
|
|
366
|
+
tx
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
// When: Thread output 설정 후 Instance에 집계
|
|
370
|
+
const threadOutput = { action: 'Fixed', result: 'success' }
|
|
371
|
+
thread.output = threadOutput
|
|
372
|
+
thread.state = ActivityThreadStatus.Ended
|
|
373
|
+
await tx.save('ActivityThread', thread)
|
|
374
|
+
|
|
375
|
+
// Instance output 업데이트
|
|
376
|
+
instance.output = threadOutput
|
|
377
|
+
const updated = await tx.save('ActivityInstance', instance)
|
|
378
|
+
|
|
379
|
+
// Then
|
|
380
|
+
expect(updated.output).toEqual(threadOutput)
|
|
381
|
+
})
|
|
382
|
+
})
|
|
383
|
+
})
|
|
384
|
+
})
|