1
1
import { beforeEach , describe , expect , it , vi } from 'vitest' ;
2
2
import { createCLI } from './cli.js' ;
3
- import * as exampleModule from './tools/example.js' ;
4
- import * as fetchExampleModule from './tools/fetch-example.js' ;
3
+ import * as retrieveModule from './tools/retrieve.js' ;
4
+ import * as saveModule from './tools/save.js' ;
5
+ import * as searchModule from './tools/search.js' ;
6
+ import * as statusModule from './tools/status.js' ;
5
7
6
- vi . mock ( './tools/example.js' ) ;
7
- vi . mock ( './tools/fetch-example.js' ) ;
8
+ vi . mock ( './tools/save.js' ) ;
9
+ vi . mock ( './tools/retrieve.js' ) ;
10
+ vi . mock ( './tools/search.js' ) ;
11
+ vi . mock ( './tools/status.js' ) ;
8
12
9
13
describe ( 'CLI' , ( ) => {
10
14
let consoleLogSpy : ReturnType < typeof vi . spyOn > ;
@@ -18,172 +22,83 @@ describe('CLI', () => {
18
22
19
23
it ( 'should create CLI program' , ( ) => {
20
24
const program = createCLI ( ) ;
21
- expect ( program . name ( ) ) . toBe ( 'mcp-template ' ) ;
22
- expect ( program . description ( ) ) . toContain ( 'MCP template ' ) ;
25
+ expect ( program . name ( ) ) . toBe ( 'wayback ' ) ;
26
+ expect ( program . description ( ) ) . toContain ( 'Wayback Machine ' ) ;
23
27
} ) ;
24
28
25
- it ( 'should handle example command' , async ( ) => {
26
- vi . spyOn ( exampleModule , 'exampleTool' ) . mockResolvedValue ( {
27
- content : [
28
- {
29
- type : 'text' ,
30
- text : 'Echo: Hello World' ,
31
- } ,
32
- ] ,
29
+ it ( 'should handle save command' , async ( ) => {
30
+ vi . spyOn ( saveModule , 'saveUrl' ) . mockResolvedValue ( {
31
+ success : true ,
32
+ message : 'Saved' ,
33
+ archivedUrl : 'https://web.archive.org/web/123/https://example.com' ,
34
+ timestamp : '123' ,
33
35
} ) ;
34
36
35
37
const program = createCLI ( ) ;
36
- await program . parseAsync ( [ 'node' , 'cli' , 'example ' , 'Hello World ' ] ) ;
38
+ await program . parseAsync ( [ 'node' , 'cli' , 'save ' , 'https://example.com ' ] ) ;
37
39
38
- expect ( exampleModule . exampleTool ) . toHaveBeenCalledWith ( {
39
- message : 'Hello World' ,
40
- uppercase : false ,
41
- } ) ;
40
+ expect ( saveModule . saveUrl ) . toHaveBeenCalledWith ( { url : 'https://example.com' } ) ;
42
41
} ) ;
43
42
44
- it ( 'should handle example command with uppercase option' , async ( ) => {
45
- vi . spyOn ( exampleModule , 'exampleTool' ) . mockResolvedValue ( {
46
- content : [
47
- {
48
- type : 'text' ,
49
- text : 'Echo: HELLO WORLD' ,
50
- } ,
51
- ] ,
43
+ it ( 'should handle get command' , async ( ) => {
44
+ vi . spyOn ( retrieveModule , 'getArchivedUrl' ) . mockResolvedValue ( {
45
+ success : true ,
46
+ message : 'Archive found' ,
47
+ available : true ,
48
+ archivedUrl : 'https://web.archive.org/web/123/https://example.com' ,
49
+ timestamp : '123' ,
52
50
} ) ;
53
51
54
52
const program = createCLI ( ) ;
55
- await program . parseAsync ( [ 'node' , 'cli' , 'example ' , 'Hello World' , '--uppercase '] ) ;
53
+ await program . parseAsync ( [ 'node' , 'cli' , 'get ' , 'https://example.com ' ] ) ;
56
54
57
- expect ( exampleModule . exampleTool ) . toHaveBeenCalledWith ( {
58
- message : 'Hello World ' ,
59
- uppercase : true ,
55
+ expect ( retrieveModule . getArchivedUrl ) . toHaveBeenCalledWith ( {
56
+ url : 'https://example.com ' ,
57
+ timestamp : undefined ,
60
58
} ) ;
61
59
} ) ;
62
60
63
- it ( 'should handle errors gracefully' , async ( ) => {
64
- const mockProcessExit = vi . spyOn ( process , 'exit' ) . mockImplementation ( ( ) => {
65
- throw new Error ( 'Process exit called' ) ;
66
- } ) ;
67
-
68
- vi . spyOn ( exampleModule , 'exampleTool' ) . mockRejectedValue ( new Error ( 'Test error' ) ) ;
69
-
70
- const program = createCLI ( ) ;
71
-
72
- try {
73
- await program . parseAsync ( [ 'node' , 'cli' , 'example' , 'Hello World' ] ) ;
74
- } catch ( error ) {
75
- // Expected to throw due to process.exit mock
76
- }
77
-
78
- expect ( mockProcessExit ) . toHaveBeenCalledWith ( 1 ) ;
79
- mockProcessExit . mockRestore ( ) ;
80
- } ) ;
81
-
82
- it ( 'should handle fetch-example command' , async ( ) => {
83
- vi . spyOn ( fetchExampleModule , 'fetchExampleTool' ) . mockResolvedValue ( {
84
- content : [
61
+ it ( 'should handle search command' , async ( ) => {
62
+ vi . spyOn ( searchModule , 'searchArchives' ) . mockResolvedValue ( {
63
+ success : true ,
64
+ message : 'Found archives' ,
65
+ results : [
85
66
{
86
- type : 'text' ,
87
- text : '# Fetch Example Results\n\nURL: https://httpbin.org/json\nStatus: 200 OK' ,
67
+ url : 'https://example.com' ,
68
+ archivedUrl : 'https://web.archive.org/web/123/https://example.com' ,
69
+ timestamp : '123' ,
70
+ date : '2023-01-01' ,
71
+ statusCode : '200' ,
72
+ mimeType : 'text/html' ,
88
73
} ,
89
74
] ,
90
- isError : false ,
75
+ totalResults : 1 ,
91
76
} ) ;
92
77
93
78
const program = createCLI ( ) ;
94
- await program . parseAsync ( [ 'node' , 'cli' , 'fetch-example' , 'https://httpbin.org/json' ] ) ;
95
-
96
- expect ( fetchExampleModule . fetchExampleTool ) . toHaveBeenCalledWith ( {
97
- url : 'https://httpbin.org/json' ,
98
- } ) ;
99
- } ) ;
100
-
101
- it ( 'should handle fetch-example command with options' , async ( ) => {
102
- vi . spyOn ( fetchExampleModule , 'fetchExampleTool' ) . mockResolvedValue ( {
103
- content : [
104
- {
105
- type : 'text' ,
106
- text : '# Fetch Example Results\n\nURL: https://httpbin.org/json\nBackend: cache-memory' ,
107
- } ,
108
- ] ,
109
- isError : false ,
110
- } ) ;
79
+ await program . parseAsync ( [ 'node' , 'cli' , 'search' , 'https://example.com' ] ) ;
111
80
112
- const program = createCLI ( ) ;
113
- await program . parseAsync ( [
114
- 'node' ,
115
- 'cli' ,
116
- 'fetch-example' ,
117
- 'https://httpbin.org/json' ,
118
- '--backend' ,
119
- 'cache-memory' ,
120
- '--no-cache' ,
121
- '--user-agent' ,
122
- 'Test-Agent/1.0' ,
123
- ] ) ;
124
-
125
- expect ( fetchExampleModule . fetchExampleTool ) . toHaveBeenCalledWith ( {
126
- url : 'https://httpbin.org/json' ,
127
- backend : 'cache-memory' ,
128
- no_cache : true ,
129
- user_agent : 'Test-Agent/1.0' ,
81
+ expect ( searchModule . searchArchives ) . toHaveBeenCalledWith ( {
82
+ url : 'https://example.com' ,
83
+ limit : 10 ,
130
84
} ) ;
131
85
} ) ;
132
86
133
- it ( 'should handle configure-fetch command' , async ( ) => {
134
- vi . spyOn ( fetchExampleModule , 'configureFetchTool' ) . mockResolvedValue ( {
135
- content : [
136
- {
137
- type : 'text' ,
138
- text : '# Fetch Configuration Updated\n\nBackend: cache-disk\nCache TTL: 60000ms' ,
139
- } ,
140
- ] ,
141
- isError : false ,
87
+ it ( 'should handle status command' , async ( ) => {
88
+ vi . spyOn ( statusModule , 'checkArchiveStatus' ) . mockResolvedValue ( {
89
+ success : true ,
90
+ message : 'Status checked' ,
91
+ isArchived : true ,
92
+ totalCaptures : 100 ,
93
+ firstCapture : '2020-01-01' ,
94
+ lastCapture : '2023-12-31' ,
142
95
} ) ;
143
96
144
97
const program = createCLI ( ) ;
145
- await program . parseAsync ( [
146
- 'node' ,
147
- 'cli' ,
148
- 'configure-fetch' ,
149
- '--backend' ,
150
- 'cache-disk' ,
151
- '--cache-ttl' ,
152
- '60000' ,
153
- '--clear-cache' ,
154
- ] ) ;
155
-
156
- expect ( fetchExampleModule . configureFetchTool ) . toHaveBeenCalledWith ( {
157
- backend : 'cache-disk' ,
158
- cache_ttl : 60000 ,
159
- clear_cache : true ,
160
- } ) ;
161
- } ) ;
98
+ await program . parseAsync ( [ 'node' , 'cli' , 'status' , 'https://example.com' ] ) ;
162
99
163
- it ( 'should handle fetch-example errors' , async ( ) => {
164
- const mockProcessExit = vi . spyOn ( process , 'exit' ) . mockImplementation ( ( ) => {
165
- throw new Error ( 'Process exit called' ) ;
100
+ expect ( statusModule . checkArchiveStatus ) . toHaveBeenCalledWith ( {
101
+ url : 'https://example.com' ,
166
102
} ) ;
167
-
168
- vi . spyOn ( fetchExampleModule , 'fetchExampleTool' ) . mockResolvedValue ( {
169
- content : [
170
- {
171
- type : 'text' ,
172
- text : 'Network error occurred' ,
173
- } ,
174
- ] ,
175
- isError : true ,
176
- } ) ;
177
-
178
- const program = createCLI ( ) ;
179
-
180
- try {
181
- await program . parseAsync ( [ 'node' , 'cli' , 'fetch-example' , 'https://invalid-url' ] ) ;
182
- } catch ( error ) {
183
- // Expected to throw due to process.exit mock
184
- }
185
-
186
- expect ( mockProcessExit ) . toHaveBeenCalledWith ( 1 ) ;
187
- mockProcessExit . mockRestore ( ) ;
188
103
} ) ;
189
104
} ) ;
0 commit comments