|
8 | 8 | * @copyright (C) 2020 LemonCloud Co Ltd. - All Rights Reserved. |
9 | 9 | */ |
10 | 10 | import { LambdaWEBHandler, LambdaHandler } from '../cores/lambda'; |
11 | | -import { ProtocolParam, Elastic6QueryService } from '../cores'; |
| 11 | +import { ProtocolParam, Elastic6QueryService, SimpleSearchParam } from '../cores'; |
12 | 12 | import { buildEngine } from '../engine'; |
13 | 13 | import { buildExpress } from '../tools'; |
14 | 14 | import { expect2, GETERR } from '../common/test-helper'; |
@@ -43,12 +43,21 @@ class MyGeneralAPIController extends GeneralAPIController<TypedStorageService<$p |
43 | 43 | } |
44 | 44 |
|
45 | 45 | //* create instance. |
46 | | -export const instance = (type: 'dummy', unique?: string) => { |
| 46 | +export const instance = (type: 'dummy', unique?: string, withSearch = false) => { |
47 | 47 | const { storage2 } = $proxy.instance(type == 'dummy' ? 'dummy-account-data.yml' : type); |
48 | 48 | const $lambda = new LambdaHandler(); |
49 | 49 | const $web = new LambdaWEBHandlerLocal($lambda); |
50 | 50 | const storage = storage2.makeTypedStorageService('test'); |
51 | | - const controller = new MyGeneralAPIController('test', storage, null, unique); |
| 51 | + //* create mock search service if requested |
| 52 | + const search = withSearch |
| 53 | + ? ({ |
| 54 | + searchSimple: async (param: SimpleSearchParam) => { |
| 55 | + return { total: 0, list: [] as any[], page: param?.$page || 0, limit: param?.$limit || 12 }; |
| 56 | + }, |
| 57 | + } as any) |
| 58 | + : null; |
| 59 | + const controller = new MyGeneralAPIController('test', storage, search, unique); |
| 60 | + |
52 | 61 | $web.addController(controller); |
53 | 62 | //* build engine + express.app. |
54 | 63 | const $engine = buildEngine({}); |
@@ -411,5 +420,118 @@ describe('GeneralController', () => { |
411 | 420 | expect2(await storage.read('#name/BBB').catch(GETERR), 'id,type,stereo,meta').toEqual( |
412 | 421 | '404 NOT FOUND - _id:TT:test:#name/BBB', |
413 | 422 | ); // lookup-data (no exists) |
| 423 | + |
| 424 | + //* listBase test - search is null |
| 425 | + try { |
| 426 | + await request(app).get('/test?page=1&limit=5'); |
| 427 | + } catch (err) { |
| 428 | + expect2(err.message.includes('searchSimple')).toEqual(true); |
| 429 | + } |
| 430 | + |
| 431 | + //* asFuncName test - base function mapping |
| 432 | + expect2(controller.asFuncName('GET', 'test', '')).toEqual('getBase'); // actually mapped to getBase |
| 433 | + expect2(controller.asFuncName('GET', 'base', '')).toEqual('getBase'); |
| 434 | + }); |
| 435 | + |
| 436 | + //* test listBase with search service |
| 437 | + it('should pass listBase() with search service', async () => { |
| 438 | + const { controller, app } = instance('dummy', undefined, true); |
| 439 | + expect2(() => controller.hello()).toEqual('general-api-controller:test'); |
| 440 | + |
| 441 | + //* test listBase with default params |
| 442 | + expect2(await request(app).get('/test'), 'status,body').toEqual({ |
| 443 | + status: 200, |
| 444 | + body: { total: 0, list: [], page: 0, limit: 12 }, |
| 445 | + }); |
| 446 | + |
| 447 | + //* test listBase with custom page & limit |
| 448 | + expect2(await request(app).get('/test?page=2&limit=20'), 'status,body').toEqual({ |
| 449 | + status: 200, |
| 450 | + body: { total: 0, list: [], page: 2, limit: 20 }, |
| 451 | + }); |
| 452 | + |
| 453 | + //* test listBase with ipp (legacy parameter) |
| 454 | + expect2(await request(app).get('/test?page=1&ipp=10'), 'status,body').toEqual({ |
| 455 | + status: 200, |
| 456 | + body: { total: 0, list: [], page: 1, limit: 10 }, |
| 457 | + }); |
| 458 | + }); |
| 459 | + |
| 460 | + //* test edge cases |
| 461 | + it('should pass edge cases', async () => { |
| 462 | + const { controller, app, storage } = instance('dummy', 'name', true); |
| 463 | + |
| 464 | + //* test deleteBase with destroy and unique field |
| 465 | + //* first create an item |
| 466 | + const created = (await request(app).post('/test/edge1').send({ name: 'ToDelete' })).body; |
| 467 | + expect2(created, 'id,type,name').toEqual({ id: 'edge1', type: 'test', name: 'ToDelete' }); |
| 468 | + |
| 469 | + //* verify lookup was created |
| 470 | + expect2(await storage.read('#name/ToDelete').catch(GETERR), 'id,stereo,meta').toEqual({ |
| 471 | + id: '#name/ToDelete', |
| 472 | + stereo: '#', |
| 473 | + meta: 'edge1', |
| 474 | + }); |
| 475 | + |
| 476 | + //* delete with destroy |
| 477 | + const deleteResult = await request(app).delete('/test/edge1?destroy'); |
| 478 | + expect2(typeof deleteResult.body.deletedAt).toEqual('number'); |
| 479 | + |
| 480 | + //* verify both item and lookup are deleted |
| 481 | + expect2(await storage.read('edge1').catch(GETERR)).toEqual('404 NOT FOUND - _id:TT:test:edge1'); |
| 482 | + expect2(await storage.read('#name/ToDelete').catch(GETERR)).toEqual( |
| 483 | + '404 NOT FOUND - _id:TT:test:#name/ToDelete', |
| 484 | + ); |
| 485 | + |
| 486 | + //* test listBase with null param |
| 487 | + const result1 = await controller.listBase('', null, null, null as any); |
| 488 | + expect2(result1, 'total,page,limit').toEqual({ total: 0, page: 0, limit: 12 }); |
| 489 | + |
| 490 | + //* test deleteBase with null param |
| 491 | + await controller.postBase('nulltest', null, { name: 'NullTest' }, null); |
| 492 | + const result2 = await controller.deleteBase('nulltest', null, null, null); |
| 493 | + expect2(result2.deletedAt > 0).toEqual(true); |
| 494 | + |
| 495 | + //* test deleteBase with destroy on non-existent item |
| 496 | + //* this tests the `: ''` branch where $org is null |
| 497 | + await request(app).delete('/test/never-existed?destroy'); |
| 498 | + |
| 499 | + //* test postBase with id='0' to trigger auto-id generation |
| 500 | + const post0Result = await request(app).post('/test/0').send({ name: 'AutoID' }); |
| 501 | + expect2(post0Result.body.type).toEqual('test'); |
| 502 | + expect2(typeof post0Result.body.id).toEqual('string'); |
| 503 | + |
| 504 | + //* cleanup |
| 505 | + if (post0Result.body.id) await storage.delete(post0Result.body.id, true); |
| 506 | + |
| 507 | + //* test putBase with various id types |
| 508 | + await controller.postBase('testput2', null, { name: 'TestPut2' }, null); |
| 509 | + const putResult = await controller.putBase('testput2' as any, null, { extra: 'data' }, null); |
| 510 | + expect2(putResult, 'id').toEqual({ id: 'testput2' }); |
| 511 | + |
| 512 | + //* test postBase with id parameter |
| 513 | + const postResult = await controller.postBase('testpost2' as any, null, { name: 'TestPost2' }, null); |
| 514 | + expect2(postResult, 'id').toEqual({ id: 'testpost2' }); |
| 515 | + |
| 516 | + //* test with id that has whitespace |
| 517 | + await controller.postBase(' testid3 ', null, { name: 'TrimTest' }, null); |
| 518 | + const trimResult = await controller.putBase(' testid3 ' as any, null, { data: 'trimmed' }, null); |
| 519 | + expect2(trimResult, 'id').toEqual({ id: 'testid3' }); |
| 520 | + |
| 521 | + //* test with falsy id |
| 522 | + expect2(await controller.putBase(null as any, null, {}, null).catch(GETERR)).toEqual( |
| 523 | + '@id (string) is required!', |
| 524 | + ); |
| 525 | + expect2(await controller.postBase(undefined as any, null, {}, null).catch(GETERR)).toEqual( |
| 526 | + '@id (string) is required!', |
| 527 | + ); |
| 528 | + |
| 529 | + //* cleanup |
| 530 | + await storage.delete('testput2', true); |
| 531 | + await storage.delete('testpost2', true); |
| 532 | + await storage.delete('testid3', true); |
| 533 | + await storage.delete('#name/TestPut2', true); |
| 534 | + await storage.delete('#name/TestPost2', true); |
| 535 | + await storage.delete('#name/TrimTest', true); |
414 | 536 | }); |
415 | 537 | }); |
0 commit comments