@tak-ps/node-tak 12.33.0 → 12.36.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.
@@ -369,3 +369,262 @@ test('Mission.getArchive throws on a TAK Server error instead of streaming an em
369
369
  mock.restore();
370
370
  }
371
371
  });
372
+
373
+ test('Mission.parent uses the name parent endpoint and unwraps the mission', async () => {
374
+ const originalRequest = Client.prototype.request;
375
+
376
+ let captured: RequestArgs | undefined;
377
+
378
+ Client.prototype.request = async function(opts: RequestArgs): Promise<Dispatcher.ResponseData> {
379
+ captured = opts;
380
+ return mockResponse(200, 'application/json', JSON.stringify({
381
+ version: '3', type: 'Mission', nodeId: 'n', data: { name: 'parent-1', guid: '11111111-2222-3333-4444-555555555555' }
382
+ }));
383
+ };
384
+
385
+ try {
386
+ const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
387
+
388
+ const parent = await api.Mission.parent('child 1');
389
+
390
+ assert.ok(captured);
391
+ assert.equal(captured.method, 'GET');
392
+ assert.equal(captured.path, '/Marti/api/missions/child%201/parent');
393
+ assert.equal(parent.name, 'parent-1');
394
+ assert.equal(parent.description, '');
395
+ } finally {
396
+ Client.prototype.request = originalRequest;
397
+ }
398
+ });
399
+
400
+ test('Mission.parent resolves a GUID to a name first', async () => {
401
+ const originalRequest = Client.prototype.request;
402
+
403
+ const paths: string[] = [];
404
+
405
+ Client.prototype.request = async function(opts: RequestArgs): Promise<Dispatcher.ResponseData> {
406
+ paths.push(String(opts.path));
407
+
408
+ if (paths.length === 1) {
409
+ return mockResponse(200, 'application/json', JSON.stringify({
410
+ version: '3', type: 'Mission', nodeId: 'n', data: [{ name: 'child-1', guid: '11111111-2222-3333-4444-555555555555' }]
411
+ }));
412
+ }
413
+
414
+ return mockResponse(200, 'application/json', JSON.stringify({
415
+ version: '3', type: 'Mission', nodeId: 'n', data: { name: 'parent-1', guid: '22222222-2222-3333-4444-555555555555' }
416
+ }));
417
+ };
418
+
419
+ try {
420
+ const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
421
+
422
+ const parent = await api.Mission.parent('11111111-2222-3333-4444-555555555555');
423
+
424
+ assert.deepEqual(paths, [
425
+ '/Marti/api/missions/guid/11111111-2222-3333-4444-555555555555',
426
+ '/Marti/api/missions/child-1/parent'
427
+ ]);
428
+ assert.equal(parent.name, 'parent-1');
429
+ } finally {
430
+ Client.prototype.request = originalRequest;
431
+ }
432
+ });
433
+
434
+ test('Mission.clearParent issues a DELETE on the guid parent endpoint', async () => {
435
+ const originalRequest = Client.prototype.request;
436
+
437
+ let captured: RequestArgs | undefined;
438
+
439
+ Client.prototype.request = async function(opts: RequestArgs): Promise<Dispatcher.ResponseData> {
440
+ captured = opts;
441
+ return mockResponse(200, 'text/plain', '');
442
+ };
443
+
444
+ try {
445
+ const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
446
+
447
+ const res = await api.Mission.clearParent('11111111-2222-3333-4444-555555555555');
448
+
449
+ assert.equal(res, undefined);
450
+ assert.ok(captured);
451
+ assert.equal(captured.method, 'DELETE');
452
+ assert.equal(captured.path, '/Marti/api/missions/guid/11111111-2222-3333-4444-555555555555/parent');
453
+ } finally {
454
+ Client.prototype.request = originalRequest;
455
+ }
456
+ });
457
+
458
+ test('Mission.update sends defaultRole alongside the current mission values', async () => {
459
+ const originalRequest = Client.prototype.request;
460
+
461
+ const captured: RequestArgs[] = [];
462
+
463
+ Client.prototype.request = async function(opts: RequestArgs): Promise<Dispatcher.ResponseData> {
464
+ captured.push(opts);
465
+ return mockResponse(200, 'application/json', JSON.stringify({
466
+ version: '3',
467
+ type: 'Mission',
468
+ data: [{
469
+ name: 'mission-1',
470
+ guid: '9d2b7a6e-3c4f-4e8a-9b1d-2f6a8c0e4b71',
471
+ createTime: '2024-01-01T00:00:00Z',
472
+ description: 'desc',
473
+ tool: 'public',
474
+ keywords: [],
475
+ externalData: [],
476
+ feeds: [],
477
+ mapLayers: [],
478
+ inviteOnly: false,
479
+ expiration: -1,
480
+ uids: [],
481
+ contents: [],
482
+ passwordProtected: false,
483
+ defaultRole: { type: 'MISSION_SUBSCRIBER', permissions: ['MISSION_READ', 'MISSION_WRITE'] },
484
+ groups: ['__ANON__']
485
+ }],
486
+ nodeId: 'node'
487
+ }));
488
+ };
489
+
490
+ try {
491
+ const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
492
+
493
+ const mission = await api.Mission.update('mission-1', {
494
+ defaultRole: MissionSubscriberRole.MISSION_READONLY_SUBSCRIBER
495
+ });
496
+
497
+ assert.equal(mission.defaultRole?.type, 'MISSION_SUBSCRIBER');
498
+ assert.equal(captured.length, 2);
499
+ assert.equal(captured[1].method, 'POST');
500
+
501
+ const url = new URL(String(captured[1].path), 'https://tak.example.com');
502
+ assert.equal(url.pathname, '/Marti/api/missions/mission-1');
503
+ assert.equal(url.searchParams.get('defaultRole'), 'MISSION_READONLY_SUBSCRIBER');
504
+ assert.equal(url.searchParams.get('description'), 'desc');
505
+ assert.equal(url.searchParams.get('group'), '__ANON__');
506
+ assert.equal(url.searchParams.get('allowDupe'), 'false');
507
+ } finally {
508
+ Client.prototype.request = originalRequest;
509
+ }
510
+ });
511
+
512
+ test('Mission.update omits defaultRole when it is not provided', async () => {
513
+ const originalRequest = Client.prototype.request;
514
+
515
+ const captured: RequestArgs[] = [];
516
+
517
+ Client.prototype.request = async function(opts: RequestArgs): Promise<Dispatcher.ResponseData> {
518
+ captured.push(opts);
519
+ return mockResponse(200, 'application/json', JSON.stringify({
520
+ version: '3',
521
+ type: 'Mission',
522
+ data: [{
523
+ name: 'mission-1',
524
+ guid: '9d2b7a6e-3c4f-4e8a-9b1d-2f6a8c0e4b71',
525
+ createTime: '2024-01-01T00:00:00Z',
526
+ description: 'desc',
527
+ tool: 'public',
528
+ keywords: [],
529
+ externalData: [],
530
+ feeds: [],
531
+ mapLayers: [],
532
+ inviteOnly: false,
533
+ expiration: -1,
534
+ uids: [],
535
+ contents: [],
536
+ passwordProtected: false,
537
+ defaultRole: { type: 'MISSION_SUBSCRIBER', permissions: [] }
538
+ }],
539
+ nodeId: 'node'
540
+ }));
541
+ };
542
+
543
+ try {
544
+ const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
545
+
546
+ await api.Mission.update('mission-1', { description: 'next' });
547
+
548
+ const url = new URL(String(captured[1].path), 'https://tak.example.com');
549
+ assert.equal(url.searchParams.has('defaultRole'), false);
550
+ assert.equal(url.searchParams.get('description'), 'next');
551
+ } finally {
552
+ Client.prototype.request = originalRequest;
553
+ }
554
+ });
555
+
556
+ test('Mission.setPassword issues a PUT on the guid password endpoint', async () => {
557
+ const originalRequest = Client.prototype.request;
558
+
559
+ let captured: RequestArgs | undefined;
560
+
561
+ Client.prototype.request = async function(opts: RequestArgs): Promise<Dispatcher.ResponseData> {
562
+ captured = opts;
563
+ return mockResponse(200, 'text/plain', '');
564
+ };
565
+
566
+ try {
567
+ const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
568
+
569
+ await api.Mission.setPassword('9d2b7a6e-3c4f-4e8a-9b1d-2f6a8c0e4b71', 'p%ss?w"rd', {
570
+ token: 'mission-token'
571
+ });
572
+
573
+ assert.ok(captured);
574
+ assert.equal(captured.method, 'PUT');
575
+
576
+ const url = new URL(String(captured.path), 'https://tak.example.com');
577
+ assert.equal(url.pathname, '/Marti/api/missions/guid/9d2b7a6e-3c4f-4e8a-9b1d-2f6a8c0e4b71/password');
578
+ assert.equal(url.searchParams.get('password'), 'p%ss?w"rd');
579
+ assert.equal((captured.headers as Record<string, string>).MissionAuthorization, 'Bearer mission-token');
580
+ } finally {
581
+ Client.prototype.request = originalRequest;
582
+ }
583
+ });
584
+
585
+ test('Mission.setPassword rejects an empty password without calling TAK Server', async () => {
586
+ const originalRequest = Client.prototype.request;
587
+
588
+ let called = false;
589
+
590
+ Client.prototype.request = async function(): Promise<Dispatcher.ResponseData> {
591
+ called = true;
592
+ return mockResponse(200, 'text/plain', '');
593
+ };
594
+
595
+ try {
596
+ const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
597
+
598
+ await assert.rejects(
599
+ api.Mission.setPassword('mission-1', ''),
600
+ { status: 400, message: 'Mission Password cannot be empty' }
601
+ );
602
+
603
+ assert.equal(called, false);
604
+ } finally {
605
+ Client.prototype.request = originalRequest;
606
+ }
607
+ });
608
+
609
+ test('Mission.removePassword issues a DELETE on the name password endpoint', async () => {
610
+ const originalRequest = Client.prototype.request;
611
+
612
+ let captured: RequestArgs | undefined;
613
+
614
+ Client.prototype.request = async function(opts: RequestArgs): Promise<Dispatcher.ResponseData> {
615
+ captured = opts;
616
+ return mockResponse(200, 'text/plain', '');
617
+ };
618
+
619
+ try {
620
+ const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
621
+
622
+ await api.Mission.removePassword('Test Mission', undefined, 'creator-1');
623
+
624
+ assert.ok(captured);
625
+ assert.equal(captured.method, 'DELETE');
626
+ assert.equal(captured.path, '/Marti/api/missions/Test%20Mission/password?creatorUid=creator-1');
627
+ } finally {
628
+ Client.prototype.request = originalRequest;
629
+ }
630
+ });