@lkangd/cc-env 1.0.0
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/.claude/settings.json +6 -0
- package/.claude/settings.local.json +3 -0
- package/.nvmrc +1 -0
- package/dist/cli.js +266 -0
- package/dist/commands/debug.js +17 -0
- package/dist/commands/init.js +64 -0
- package/dist/commands/preset/create.js +61 -0
- package/dist/commands/preset/delete.js +25 -0
- package/dist/commands/preset/edit.js +15 -0
- package/dist/commands/preset/list.js +16 -0
- package/dist/commands/preset/show.js +16 -0
- package/dist/commands/restore.js +65 -0
- package/dist/commands/run.js +80 -0
- package/dist/core/errors.js +11 -0
- package/dist/core/find-claude.js +64 -0
- package/dist/core/format.js +23 -0
- package/dist/core/fs.js +12 -0
- package/dist/core/gitignore.js +23 -0
- package/dist/core/lock.js +25 -0
- package/dist/core/logger.js +8 -0
- package/dist/core/mask.js +13 -0
- package/dist/core/paths.js +32 -0
- package/dist/core/process-env.js +4 -0
- package/dist/core/schema.js +38 -0
- package/dist/core/spawn.js +26 -0
- package/dist/flows/init-flow.js +35 -0
- package/dist/flows/preset-create-flow.js +80 -0
- package/dist/flows/restore-flow.js +75 -0
- package/dist/ink/init-app.js +54 -0
- package/dist/ink/preset-create-app.js +271 -0
- package/dist/ink/preset-delete-app.js +47 -0
- package/dist/ink/preset-list-app.js +27 -0
- package/dist/ink/preset-show-app.js +27 -0
- package/dist/ink/restore-app.js +102 -0
- package/dist/ink/run-preset-select-app.js +31 -0
- package/dist/ink/summary.js +28 -0
- package/dist/services/claude-settings-env-service.js +55 -0
- package/dist/services/config-service.js +26 -0
- package/dist/services/history-service.js +39 -0
- package/dist/services/preset-service.js +61 -0
- package/dist/services/project-env-service.js +90 -0
- package/dist/services/project-state-service.js +26 -0
- package/dist/services/runtime-env-service.js +13 -0
- package/dist/services/settings-env-service.js +36 -0
- package/dist/services/shell-env-service.js +77 -0
- package/docs/product-specs/index.draft.md +106 -0
- package/docs/product-specs/index.md +911 -0
- package/docs/product-specs/optional.md +42 -0
- package/docs/references/claude-code-env.md +224 -0
- package/docs/superpowers/plans/2026-04-24-cc-env-init-shell-migration.md +1331 -0
- package/docs/superpowers/plans/2026-04-24-cc-env.md +1666 -0
- package/docs/superpowers/plans/2026-04-26-preset-create-interactive-refactor.md +1432 -0
- package/docs/superpowers/specs/2026-04-24-cc-env-design.md +438 -0
- package/docs/superpowers/specs/2026-04-24-cc-env-init-shell-migration-design.md +181 -0
- package/docs/superpowers/specs/2026-04-26-preset-create-interactive-refactor-design.md +78 -0
- package/package.json +55 -0
- package/src/cli.ts +337 -0
- package/src/commands/init.ts +139 -0
- package/src/commands/preset/create.ts +96 -0
- package/src/commands/preset/delete.ts +62 -0
- package/src/commands/preset/show.ts +51 -0
- package/src/commands/restore.ts +150 -0
- package/src/commands/run.ts +158 -0
- package/src/core/errors.ts +13 -0
- package/src/core/find-claude.ts +70 -0
- package/src/core/format.ts +29 -0
- package/src/core/fs.ts +18 -0
- package/src/core/gitignore.ts +26 -0
- package/src/core/logger.ts +11 -0
- package/src/core/mask.ts +17 -0
- package/src/core/paths.ts +41 -0
- package/src/core/process-env.ts +11 -0
- package/src/core/schema.ts +55 -0
- package/src/core/spawn.ts +36 -0
- package/src/flows/init-flow.ts +61 -0
- package/src/flows/preset-create-flow.ts +129 -0
- package/src/flows/restore-flow.ts +144 -0
- package/src/ink/init-app.tsx +110 -0
- package/src/ink/preset-create-app.tsx +451 -0
- package/src/ink/preset-delete-app.tsx +114 -0
- package/src/ink/preset-show-app.tsx +76 -0
- package/src/ink/restore-app.tsx +230 -0
- package/src/ink/run-preset-select-app.tsx +83 -0
- package/src/ink/summary.tsx +91 -0
- package/src/services/claude-settings-env-service.ts +72 -0
- package/src/services/history-service.ts +48 -0
- package/src/services/preset-service.ts +72 -0
- package/src/services/project-env-service.ts +128 -0
- package/src/services/project-state-service.ts +31 -0
- package/src/services/settings-env-service.ts +40 -0
- package/src/services/shell-env-service.ts +112 -0
- package/src/types.d.ts +19 -0
- package/tests/cli/help.test.ts +133 -0
- package/tests/cli/init.test.ts +76 -0
- package/tests/cli/restore.test.ts +172 -0
- package/tests/commands/create.test.ts +263 -0
- package/tests/commands/output.test.ts +119 -0
- package/tests/commands/run.test.ts +218 -0
- package/tests/core/gitignore.test.ts +98 -0
- package/tests/core/paths.test.ts +24 -0
- package/tests/core/schema-mask.test.ts +182 -0
- package/tests/core/spawn.test.ts +47 -0
- package/tests/flows/init-flow.test.ts +40 -0
- package/tests/flows/preset-create-flow.test.ts +225 -0
- package/tests/flows/restore-flow.test.ts +157 -0
- package/tests/integration/init-restore.test.ts +406 -0
- package/tests/services/claude-shell.test.ts +183 -0
- package/tests/services/storage.test.ts +143 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +22 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
advancePresetCreateFlow,
|
|
5
|
+
createPresetCreateFlowState,
|
|
6
|
+
type PresetCreateFlowState,
|
|
7
|
+
} from '../../src/flows/preset-create-flow.js'
|
|
8
|
+
|
|
9
|
+
describe('preset create flow', () => {
|
|
10
|
+
it("starts at step 'source' with empty defaults", () => {
|
|
11
|
+
expect(createPresetCreateFlowState()).toEqual({
|
|
12
|
+
step: 'source',
|
|
13
|
+
env: {},
|
|
14
|
+
allKeys: [],
|
|
15
|
+
selectedKeys: [],
|
|
16
|
+
presetName: '',
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
describe('file path', () => {
|
|
21
|
+
function goToFilePath(): PresetCreateFlowState {
|
|
22
|
+
return advancePresetCreateFlow(createPresetCreateFlowState(), {
|
|
23
|
+
type: 'select-source',
|
|
24
|
+
source: 'file',
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
it('source=file advances to filePath', () => {
|
|
29
|
+
expect(goToFilePath().step).toBe('filePath')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('set-file-path advances to keys', () => {
|
|
33
|
+
const state = advancePresetCreateFlow(goToFilePath(), {
|
|
34
|
+
type: 'set-file-path',
|
|
35
|
+
filePath: '/path/to/env.json',
|
|
36
|
+
})
|
|
37
|
+
expect(state.step).toBe('keys')
|
|
38
|
+
expect(state.filePath).toBe('/path/to/env.json')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('set-error stays on filePath with error message', () => {
|
|
42
|
+
const state = advancePresetCreateFlow(goToFilePath(), {
|
|
43
|
+
type: 'set-error',
|
|
44
|
+
error: 'File not found',
|
|
45
|
+
})
|
|
46
|
+
expect(state.step).toBe('filePath')
|
|
47
|
+
expect(state.error).toBe('File not found')
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
describe('manual input path', () => {
|
|
52
|
+
function goToManualInput(): PresetCreateFlowState {
|
|
53
|
+
return advancePresetCreateFlow(createPresetCreateFlowState(), {
|
|
54
|
+
type: 'select-source',
|
|
55
|
+
source: 'manual',
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
it('source=manual advances to manualInput', () => {
|
|
60
|
+
expect(goToManualInput().step).toBe('manualInput')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('add-manual-pair accumulates pairs', () => {
|
|
64
|
+
const state = advancePresetCreateFlow(goToManualInput(), {
|
|
65
|
+
type: 'add-manual-pair',
|
|
66
|
+
key: 'FOO',
|
|
67
|
+
value: 'bar',
|
|
68
|
+
})
|
|
69
|
+
expect(state.env).toEqual({ FOO: 'bar' })
|
|
70
|
+
expect(state.selectedKeys).toEqual(['FOO'])
|
|
71
|
+
expect(state.step).toBe('manualInput')
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('add-manual-pair overwrites existing key', () => {
|
|
75
|
+
const first = advancePresetCreateFlow(goToManualInput(), {
|
|
76
|
+
type: 'add-manual-pair',
|
|
77
|
+
key: 'FOO',
|
|
78
|
+
value: 'bar',
|
|
79
|
+
})
|
|
80
|
+
const second = advancePresetCreateFlow(first, {
|
|
81
|
+
type: 'add-manual-pair',
|
|
82
|
+
key: 'FOO',
|
|
83
|
+
value: 'updated',
|
|
84
|
+
})
|
|
85
|
+
expect(second.env.FOO).toBe('updated')
|
|
86
|
+
expect(second.selectedKeys).toEqual(['FOO'])
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('set-error on manualInput sets error', () => {
|
|
90
|
+
const state = advancePresetCreateFlow(goToManualInput(), {
|
|
91
|
+
type: 'set-error',
|
|
92
|
+
error: 'Invalid format',
|
|
93
|
+
})
|
|
94
|
+
expect(state.error).toBe('Invalid format')
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('finish-manual-input advances to name', () => {
|
|
98
|
+
const state = advancePresetCreateFlow(goToManualInput(), {
|
|
99
|
+
type: 'finish-manual-input',
|
|
100
|
+
})
|
|
101
|
+
expect(state.step).toBe('name')
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
describe('shared path after source input', () => {
|
|
106
|
+
function goToNameViaFile(): PresetCreateFlowState {
|
|
107
|
+
const filePath = advancePresetCreateFlow(createPresetCreateFlowState(), {
|
|
108
|
+
type: 'select-source',
|
|
109
|
+
source: 'file',
|
|
110
|
+
})
|
|
111
|
+
const keys = advancePresetCreateFlow(filePath, {
|
|
112
|
+
type: 'set-file-path',
|
|
113
|
+
filePath: '/env.json',
|
|
114
|
+
})
|
|
115
|
+
return advancePresetCreateFlow(keys, {
|
|
116
|
+
type: 'select-keys',
|
|
117
|
+
keys: ['API_KEY'],
|
|
118
|
+
env: { API_KEY: 'secret' },
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function goToNameViaManual(): PresetCreateFlowState {
|
|
123
|
+
const manual = advancePresetCreateFlow(createPresetCreateFlowState(), {
|
|
124
|
+
type: 'select-source',
|
|
125
|
+
source: 'manual',
|
|
126
|
+
})
|
|
127
|
+
return advancePresetCreateFlow(manual, {
|
|
128
|
+
type: 'finish-manual-input',
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
it('set-name advances to destination', () => {
|
|
133
|
+
const state = advancePresetCreateFlow(goToNameViaFile(), {
|
|
134
|
+
type: 'set-name',
|
|
135
|
+
name: 'my-preset',
|
|
136
|
+
})
|
|
137
|
+
expect(state.step).toBe('destination')
|
|
138
|
+
expect(state.presetName).toBe('my-preset')
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('select-destination advances to confirm', () => {
|
|
142
|
+
const name = advancePresetCreateFlow(goToNameViaFile(), {
|
|
143
|
+
type: 'set-name',
|
|
144
|
+
name: 'my-preset',
|
|
145
|
+
})
|
|
146
|
+
const dest = advancePresetCreateFlow(name, {
|
|
147
|
+
type: 'select-destination',
|
|
148
|
+
destination: 'global',
|
|
149
|
+
})
|
|
150
|
+
expect(dest.step).toBe('confirm')
|
|
151
|
+
expect(dest.destination).toBe('global')
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('confirm advances to done', () => {
|
|
155
|
+
const name = advancePresetCreateFlow(goToNameViaFile(), {
|
|
156
|
+
type: 'set-name',
|
|
157
|
+
name: 'my-preset',
|
|
158
|
+
})
|
|
159
|
+
const dest = advancePresetCreateFlow(name, {
|
|
160
|
+
type: 'select-destination',
|
|
161
|
+
destination: 'project',
|
|
162
|
+
})
|
|
163
|
+
const done = advancePresetCreateFlow(dest, { type: 'confirm' })
|
|
164
|
+
expect(done.step).toBe('done')
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
it('manual path reaches done through name→destination→confirm', () => {
|
|
168
|
+
const name = advancePresetCreateFlow(goToNameViaManual(), {
|
|
169
|
+
type: 'set-name',
|
|
170
|
+
name: 'manual-preset',
|
|
171
|
+
})
|
|
172
|
+
const dest = advancePresetCreateFlow(name, {
|
|
173
|
+
type: 'select-destination',
|
|
174
|
+
destination: 'global',
|
|
175
|
+
})
|
|
176
|
+
const done = advancePresetCreateFlow(dest, { type: 'confirm' })
|
|
177
|
+
expect(done.step).toBe('done')
|
|
178
|
+
expect(done.presetName).toBe('manual-preset')
|
|
179
|
+
})
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('ignores invalid transitions without mutating state', () => {
|
|
183
|
+
const state = createPresetCreateFlowState()
|
|
184
|
+
|
|
185
|
+
expect(
|
|
186
|
+
advancePresetCreateFlow(state, {
|
|
187
|
+
type: 'select-keys',
|
|
188
|
+
keys: ['FOO'],
|
|
189
|
+
env: { FOO: 'bar' },
|
|
190
|
+
}),
|
|
191
|
+
).toEqual(state)
|
|
192
|
+
|
|
193
|
+
expect(
|
|
194
|
+
advancePresetCreateFlow(state, {
|
|
195
|
+
type: 'confirm',
|
|
196
|
+
}),
|
|
197
|
+
).toEqual(state)
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
it('ignores changes after the flow is done', () => {
|
|
201
|
+
const source = advancePresetCreateFlow(createPresetCreateFlowState(), {
|
|
202
|
+
type: 'select-source',
|
|
203
|
+
source: 'manual',
|
|
204
|
+
})
|
|
205
|
+
const name = advancePresetCreateFlow(source, {
|
|
206
|
+
type: 'finish-manual-input',
|
|
207
|
+
})
|
|
208
|
+
const dest = advancePresetCreateFlow(name, {
|
|
209
|
+
type: 'set-name',
|
|
210
|
+
name: 'test',
|
|
211
|
+
})
|
|
212
|
+
const confirm = advancePresetCreateFlow(dest, {
|
|
213
|
+
type: 'select-destination',
|
|
214
|
+
destination: 'global',
|
|
215
|
+
})
|
|
216
|
+
const done = advancePresetCreateFlow(confirm, { type: 'confirm' })
|
|
217
|
+
|
|
218
|
+
expect(
|
|
219
|
+
advancePresetCreateFlow(done, {
|
|
220
|
+
type: 'select-source',
|
|
221
|
+
source: 'file',
|
|
222
|
+
}),
|
|
223
|
+
).toEqual(done)
|
|
224
|
+
})
|
|
225
|
+
})
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
advanceRestoreFlow,
|
|
5
|
+
createRestoreFlowState,
|
|
6
|
+
} from '../../src/flows/restore-flow.js'
|
|
7
|
+
|
|
8
|
+
const initRecord = {
|
|
9
|
+
timestamp: '2026-04-24T00:00:00.000Z',
|
|
10
|
+
action: 'init' as const,
|
|
11
|
+
migratedKeys: ['ANTHROPIC_AUTH_TOKEN'],
|
|
12
|
+
sources: [
|
|
13
|
+
{
|
|
14
|
+
file: '/Users/test/.claude/settings.json',
|
|
15
|
+
backup: {},
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
file: '/Users/test/.claude/settings.local.json',
|
|
19
|
+
backup: {
|
|
20
|
+
ANTHROPIC_AUTH_TOKEN: 'local-token',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
shellWrites: [
|
|
25
|
+
{
|
|
26
|
+
shell: 'zsh' as const,
|
|
27
|
+
filePath: '/Users/test/.zshrc',
|
|
28
|
+
env: {
|
|
29
|
+
ANTHROPIC_AUTH_TOKEN: 'local-token',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const restoreRecord = {
|
|
36
|
+
timestamp: '2026-04-25T00:00:00.000Z',
|
|
37
|
+
action: 'restore' as const,
|
|
38
|
+
targetType: 'preset' as const,
|
|
39
|
+
targetName: 'openai',
|
|
40
|
+
backup: {
|
|
41
|
+
OPENAI_API_KEY: 'sk-123',
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createConfirmState() {
|
|
46
|
+
const recordState = createRestoreFlowState([restoreRecord])
|
|
47
|
+
const targetState = advanceRestoreFlow(recordState, {
|
|
48
|
+
type: 'select-record',
|
|
49
|
+
timestamp: restoreRecord.timestamp,
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return advanceRestoreFlow(targetState, {
|
|
53
|
+
type: 'select-target',
|
|
54
|
+
targetType: 'preset',
|
|
55
|
+
targetName: restoreRecord.targetName,
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe('restore flow', () => {
|
|
60
|
+
it('starts on the record step', () => {
|
|
61
|
+
expect(createRestoreFlowState([restoreRecord])).toEqual({
|
|
62
|
+
step: 'record',
|
|
63
|
+
records: [restoreRecord],
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('skips target selection for init history entries', () => {
|
|
68
|
+
const state = createRestoreFlowState([initRecord])
|
|
69
|
+
|
|
70
|
+
expect(
|
|
71
|
+
advanceRestoreFlow(state, {
|
|
72
|
+
type: 'select-record',
|
|
73
|
+
timestamp: initRecord.timestamp,
|
|
74
|
+
}),
|
|
75
|
+
).toEqual({
|
|
76
|
+
step: 'confirm',
|
|
77
|
+
records: [initRecord],
|
|
78
|
+
selectedTimestamp: initRecord.timestamp,
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('moves from record to target for restore history entries', () => {
|
|
83
|
+
const state = createRestoreFlowState([restoreRecord])
|
|
84
|
+
|
|
85
|
+
expect(
|
|
86
|
+
advanceRestoreFlow(state, {
|
|
87
|
+
type: 'select-record',
|
|
88
|
+
timestamp: restoreRecord.timestamp,
|
|
89
|
+
}),
|
|
90
|
+
).toEqual({
|
|
91
|
+
step: 'target',
|
|
92
|
+
records: [restoreRecord],
|
|
93
|
+
selectedTimestamp: restoreRecord.timestamp,
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('keeps the record step unchanged when selecting an unknown timestamp', () => {
|
|
98
|
+
const state = createRestoreFlowState([restoreRecord])
|
|
99
|
+
|
|
100
|
+
expect(
|
|
101
|
+
advanceRestoreFlow(state, {
|
|
102
|
+
type: 'select-record',
|
|
103
|
+
timestamp: '2026-04-26T00:00:00.000Z',
|
|
104
|
+
}),
|
|
105
|
+
).toEqual(state)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('moves through target, confirm, and done after selecting a restore record', () => {
|
|
109
|
+
const confirmState = createConfirmState()
|
|
110
|
+
|
|
111
|
+
expect(confirmState).toEqual({
|
|
112
|
+
step: 'confirm',
|
|
113
|
+
records: [restoreRecord],
|
|
114
|
+
selectedTimestamp: restoreRecord.timestamp,
|
|
115
|
+
targetType: 'preset',
|
|
116
|
+
targetName: restoreRecord.targetName,
|
|
117
|
+
})
|
|
118
|
+
expect(advanceRestoreFlow(confirmState, { type: 'confirm' })).toEqual({
|
|
119
|
+
step: 'done',
|
|
120
|
+
records: [restoreRecord],
|
|
121
|
+
selectedTimestamp: restoreRecord.timestamp,
|
|
122
|
+
targetType: 'preset',
|
|
123
|
+
targetName: restoreRecord.targetName,
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('finishes an init restore after confirm', () => {
|
|
128
|
+
const confirmState = advanceRestoreFlow(createRestoreFlowState([initRecord]), {
|
|
129
|
+
type: 'select-record',
|
|
130
|
+
timestamp: initRecord.timestamp,
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
expect(advanceRestoreFlow(confirmState, { type: 'confirm' })).toEqual({
|
|
134
|
+
step: 'done',
|
|
135
|
+
records: [initRecord],
|
|
136
|
+
selectedTimestamp: initRecord.timestamp,
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('keeps the done step unchanged for any later action', () => {
|
|
141
|
+
const doneState = advanceRestoreFlow(createConfirmState(), { type: 'confirm' })
|
|
142
|
+
|
|
143
|
+
expect(
|
|
144
|
+
advanceRestoreFlow(doneState, {
|
|
145
|
+
type: 'select-record',
|
|
146
|
+
timestamp: restoreRecord.timestamp,
|
|
147
|
+
}),
|
|
148
|
+
).toEqual(doneState)
|
|
149
|
+
expect(
|
|
150
|
+
advanceRestoreFlow(doneState, {
|
|
151
|
+
type: 'select-target',
|
|
152
|
+
targetType: 'settings',
|
|
153
|
+
}),
|
|
154
|
+
).toEqual(doneState)
|
|
155
|
+
expect(advanceRestoreFlow(doneState, { type: 'confirm' })).toEqual(doneState)
|
|
156
|
+
})
|
|
157
|
+
})
|