1import {
2  findObjcFunctionCodeBlock,
3  findObjcInterfaceCodeBlock,
4  findSwiftFunctionCodeBlock,
5  insertContentsInsideObjcFunctionBlock,
6  insertContentsInsideObjcInterfaceBlock,
7  insertContentsInsideSwiftClassBlock,
8  insertContentsInsideSwiftFunctionBlock,
9} from '../codeMod';
10
11describe(findObjcInterfaceCodeBlock, () => {
12  it('should find class interface', () => {
13    const contents = `\
14#import <Foundation/Foundation.h>
15
16@interface Foo : NSObject
17{
18  int value;
19}
20
21- (void)doSomething;
22@end
23
24// some comments`;
25
26    const expectContents = `\
27@interface Foo : NSObject
28{
29  int value;
30}
31
32- (void)doSomething;
33@end`;
34
35    expect(findObjcInterfaceCodeBlock(contents, '@interface Foo')).toEqual({
36      start: 35,
37      end: 104,
38      code: expectContents,
39    });
40  });
41
42  it('should find class category', () => {
43    const contents = `\
44@interface Foo() <SomeProtocol> {
45  int value;
46}
47
48- (void)doSomething;
49@end
50
51// some comments`;
52
53    const expectContents = `\
54@interface Foo() <SomeProtocol> {
55  int value;
56}
57
58- (void)doSomething;
59@end`;
60
61    expect(findObjcInterfaceCodeBlock(contents, '@interface Foo')).toEqual({
62      start: 0,
63      end: 75,
64      code: expectContents,
65    });
66  });
67
68  it('should find class implementation', () => {
69    const contents = `\
70#import <Foundation/Foundation.h>
71
72@interface Foo() <SomeProtocol> {
73  int value;
74}
75
76@implementation Foo
77
78- (void)doSomething
79{
80  // ...
81}
82
83@end
84
85// some comments`;
86
87    const expectContents = `\
88@implementation Foo
89
90- (void)doSomething
91{
92  // ...
93}
94
95@end`;
96
97    expect(findObjcInterfaceCodeBlock(contents, '@implementation Foo')).toEqual({
98      start: 85,
99      end: 144,
100      code: expectContents,
101    });
102  });
103
104  it('should returns null if not found', () => {
105    expect(findObjcInterfaceCodeBlock('', '@interface NotFound')).toBe(null);
106  });
107});
108
109describe(findObjcFunctionCodeBlock, () => {
110  it('should find function selector without arguments', () => {
111    const contents = `\
112// comments
113- (void)foo
114{
115  [self doSomething];
116}
117// comments`;
118
119    const expectContents = `\
120{
121  [self doSomething];
122}`;
123    expect(findObjcFunctionCodeBlock(contents, 'foo')).toEqual({
124      start: 24,
125      end: 48,
126      code: expectContents,
127    });
128  });
129
130  it('should find function selector with one argument', () => {
131    const contents = `\
132// comments
133- (void)foo:(NSString *)value
134{
135  [self doSomething];
136}
137// comments`;
138
139    const expectContents = `\
140{
141  [self doSomething];
142}`;
143    expect(findObjcFunctionCodeBlock(contents, 'foo:')).toEqual({
144      start: 42,
145      end: 66,
146      code: expectContents,
147    });
148  });
149
150  it('should find function selector with two arguments', () => {
151    const contents = `\
152// comments
153- (void)foo:(NSString *)value withBar:(NSString *)barValue
154{
155  [self doSomething];
156}
157// comments`;
158
159    const expectContents = `\
160{
161  [self doSomething];
162}`;
163    expect(findObjcFunctionCodeBlock(contents, 'foo:withBar:')).toEqual({
164      start: 71,
165      end: 95,
166      code: expectContents,
167    });
168  });
169
170  it('should return null if selector function not found', () => {
171    const contents = `
172// comments
173- (void)foo:(NSString *)value
174{
175  [self doSomething];
176}
177// comments`;
178
179    expect(findObjcFunctionCodeBlock(contents, 'foo')).toBe(null);
180  });
181});
182
183describe(insertContentsInsideObjcFunctionBlock, () => {
184  it('should support prepend code to the head', () => {
185    const rawContents = `
186- (void)doSomething:(NSString *)value
187{
188  [self doAnotherThing];
189}`;
190
191    const expectContents = `
192- (void)doSomething:(NSString *)value
193{
194  NSLog(@"value=%@", value);
195  [self doAnotherThing];
196}`;
197
198    expect(
199      insertContentsInsideObjcFunctionBlock(
200        rawContents,
201        'doSomething:',
202        'NSLog(@"value=%@", value);',
203        {
204          position: 'head',
205        }
206      )
207    ).toEqual(expectContents);
208  });
209
210  it('should support append code to the tail', () => {
211    const rawContents = `
212- (void)doSomething:(NSString *)value
213{
214  [self doAnotherThing];
215}`;
216
217    const expectContents = `
218- (void)doSomething:(NSString *)value
219{
220  [self doAnotherThing];
221  NSLog(@"value=%@", value);
222}`;
223
224    expect(
225      insertContentsInsideObjcFunctionBlock(
226        rawContents,
227        'doSomething:',
228        'NSLog(@"value=%@", value);',
229        {
230          position: 'tail',
231        }
232      )
233    ).toEqual(expectContents);
234  });
235
236  it('should support append code to the tail but before the last return', () => {
237    const rawContents = `
238- (BOOL)doSomething:(NSString *)value
239{
240  [self doAnotherThing];
241  return YES;
242}`;
243
244    const expectContents = `
245- (BOOL)doSomething:(NSString *)value
246{
247  [self doAnotherThing];
248  NSLog(@"value=%@", value);
249  return YES;
250}`;
251
252    expect(
253      insertContentsInsideObjcFunctionBlock(
254        rawContents,
255        'doSomething:',
256        'NSLog(@"value=%@", value);',
257        {
258          position: 'tailBeforeLastReturn',
259        }
260      )
261    ).toEqual(expectContents);
262  });
263});
264
265describe(insertContentsInsideObjcInterfaceBlock, () => {
266  it('should support append new function into class implementation', () => {
267    const contents = `\
268@interface Foo() <SomeProtocol> {
269  int value;
270}
271
272@implementation Foo
273
274- (void)doSomething
275{
276  // ...
277}
278
279@end`;
280
281    const expectContents = `\
282@interface Foo() <SomeProtocol> {
283  int value;
284}
285
286@implementation Foo
287
288- (void)doSomething
289{
290  // ...
291}
292
293- (BOOL)isFoo
294{
295  return YES;
296}
297
298@end`;
299
300    expect(
301      insertContentsInsideObjcInterfaceBlock(
302        contents,
303        '@interface Foo',
304        `\
305- (BOOL)isFoo
306{
307  return YES;
308}\n
309`,
310        { position: 'tail' }
311      )
312    ).toEqual(expectContents);
313  });
314});
315
316describe(findSwiftFunctionCodeBlock, () => {
317  it('should find function with match selector', () => {
318    const contents = `
319class Foo: NSObject {
320  func doSomething() {
321    print("Hello!")
322  }
323
324  func doSomething(forName name: String) -> Bool {
325    return true
326  }
327
328  func doSomething(_ name: String, withValue value: String) {
329    print("Hello \\(name) - value[\\(value)]!")
330  }
331}
332`;
333    expect(findSwiftFunctionCodeBlock(contents, 'doSomething(_:withValue:)')).toEqual({
334      start: 203,
335      end: 253,
336      code: ['{', '    print("Hello \\(name) - value[\\(value)]!")', '  }'].join('\n'),
337    });
338  });
339});
340
341describe(insertContentsInsideSwiftClassBlock, () => {
342  it('should support adding new property inside class code block', () => {
343    const contents = `
344// comments
345class Foo: NSObject {
346  func doSomething() {
347    // ...
348  }
349}`;
350
351    const expectContents = `
352// comments
353class Foo: NSObject {
354  var Value: String?
355
356  func doSomething() {
357    // ...
358  }
359}`;
360
361    expect(
362      insertContentsInsideSwiftClassBlock(contents, 'class Foo', '\n  var Value: String?\n', {
363        position: 'head',
364      })
365    ).toEqual(expectContents);
366  });
367});
368
369describe(insertContentsInsideSwiftFunctionBlock, () => {
370  it('should support prepend code to the head', () => {
371    const rawContents = `
372func doSomething(_ value: String!) {
373  self.doAnotherThing()
374}`;
375
376    const expectContents = `
377func doSomething(_ value: String!) {
378  print("value=\\(value)")
379  self.doAnotherThing()
380}`;
381
382    expect(
383      insertContentsInsideSwiftFunctionBlock(
384        rawContents,
385        'doSomething(_:)',
386        'print("value=\\(value)")',
387        {
388          position: 'head',
389        }
390      )
391    ).toEqual(expectContents);
392  });
393
394  it('should support append code to the tail', () => {
395    const rawContents = `
396func doSomething(_ value: String!) {
397  self.doAnotherThing()
398}`;
399
400    const expectContents = `
401func doSomething(_ value: String!) {
402  self.doAnotherThing()
403  print("value=\\(value)")
404}`;
405
406    expect(
407      insertContentsInsideSwiftFunctionBlock(
408        rawContents,
409        'doSomething(_:)',
410        'print("value=\\(value)")',
411        {
412          position: 'tail',
413        }
414      )
415    ).toEqual(expectContents);
416  });
417
418  it('should support append code to the tail but before the last return', () => {
419    const rawContents = `
420func doSomething(_ value: String!) -> Bool {
421  self.doAnotherThing()
422  return true
423}`;
424
425    const expectContents = `
426func doSomething(_ value: String!) -> Bool {
427  self.doAnotherThing()
428  print("value=\\(value)")
429  return true
430}`;
431
432    expect(
433      insertContentsInsideSwiftFunctionBlock(
434        rawContents,
435        'doSomething(_:)',
436        'print("value=\\(value)")',
437        {
438          position: 'tailBeforeLastReturn',
439        }
440      )
441    ).toEqual(expectContents);
442  });
443});
444