@jrpool/kilotest 31.2.2 → 33.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/index.js CHANGED
@@ -5,7 +5,6 @@
5
5
 
6
6
  // ENVIRONMENT
7
7
 
8
- // Module to keep secrets local.
9
8
  require('dotenv').config({quiet: true});
10
9
 
11
10
  // IMPORTS
@@ -14,13 +13,13 @@ const {
14
13
  getJobNames,
15
14
  getJSON,
16
15
  getLogPath,
17
- getLogs,
18
16
  getObject,
19
17
  getPOSTData,
20
18
  getReport,
21
19
  getRecs,
22
20
  getReportPath,
23
21
  isHidden,
22
+ isReportAvailable,
24
23
  isTimeStamp,
25
24
  isJobID,
26
25
  isURL,
@@ -29,6 +28,7 @@ const {
29
28
  reportsPath,
30
29
  ruleIDs
31
30
  } = require('./util');
31
+ const {handleMCP} = require('./mcp');
32
32
  const fs = require('fs/promises');
33
33
  const http = require('http');
34
34
  const https = require('https');
@@ -171,17 +171,6 @@ const checkBalancesForAlerts = async report => {
171
171
  }
172
172
  }
173
173
  };
174
- // Minifies a URL.
175
- const minifyURL = url => url.replace(/www\.|\/$/g, '');
176
- // Returns whether a report on a page is available.
177
- const isReportAvailable = async (what, url) => {
178
- const logs = await getLogs();
179
- const whats = logs.map(log => log.what);
180
- const urls = logs.map(log => log.url);
181
- const miniURLs = urls.map(url => minifyURL(url));
182
- const miniURL = minifyURL(url);
183
- return whats.includes(what) || miniURLs.includes(miniURL);
184
- };
185
174
  // Handles a request.
186
175
  const requestHandler = async (request, response) => {
187
176
  // Sets response headers.
@@ -218,8 +207,12 @@ const requestHandler = async (request, response) => {
218
207
  }
219
208
  // Otherwise, if the request is a GET request:
220
209
  else if (method === 'GET') {
221
- // If it is for the home page:
222
- if (['/', '/index.html'].includes(pathname)) {
210
+ // If it is for the model context protocol server:
211
+ if (pathname === '/mcp') {
212
+ await handleMCP(request, response);
213
+ }
214
+ // Otherwise, if it is for the home page:
215
+ else if (['/', '/index.html'].includes(pathname)) {
223
216
  // Get the home page.
224
217
  const homePage = await fs.readFile('index.html', 'utf8');
225
218
  // Serve it.
@@ -313,7 +306,7 @@ const requestHandler = async (request, response) => {
313
306
  const topic = pageName.slice(0, -5);
314
307
  // If the page can be generated:
315
308
  if (answer[topic]) {
316
- setHeaders('text/html', `${pathname}${search}`, 'medium');
309
+ setHeaders('text/html', `${pathname}${search}`, 'ultra');
317
310
  // Get the answer data.
318
311
  const answerData = await answer[topic](pathTail, search);
319
312
  // If they are valid:
@@ -427,53 +420,25 @@ const requestHandler = async (request, response) => {
427
420
  }
428
421
  // Otherwise, if the request is a POST request:
429
422
  else if (method === 'POST') {
430
- // Get the data from the request body.
431
- const postData = await getPOSTData(request);
432
- // If the request is a retest recommendation:
433
- if (pageName === 'retestRec.html') {
434
- const {why} = postData;
435
- const [timeStamp, jobID] = pathTail.split('/');
436
- // If the request is valid:
437
- if (isTimeStamp(timeStamp) && isJobID(jobID) && why) {
438
- // Serve response headers.
439
- setHeaders('text/html', `${pathname}${search}`, 'ultra');
440
- // Get the answer data.
441
- const answerData = await require(path.join(__dirname, 'retestRec', 'index'))
442
- .answer(pathTail, why);
443
- // If they are valid:
444
- if (answerData.status === 'ok') {
445
- // Serve the answer page.
446
- response.end(answerData.answerPage);
447
- }
448
- // Otherwise, i.e. if they are invalid:
449
- else {
450
- // Report the error.
451
- await serveError({message: answerData.error}, response, true);
452
- }
453
- }
454
- // Otherwise, i.e. if the request is invalid:
455
- else {
456
- // Report the error.
457
- await serveError({message: 'ERROR: Invalid retest recommendation'}, response, true);
458
- }
423
+ // If it is for the model context protocol server:
424
+ if (pageName === 'mcp') {
425
+ await handleMCP(request, response);
459
426
  }
460
- // Otherwise, if it is a test recommendation:
461
- else if (pageName === 'testRec.html') {
462
- const {what, url, why} = postData;
463
- // If the request is valid:
464
- if (what && url.startsWith('https://') && why) {
465
- // If a report on the page is already available:
466
- if (await isReportAvailable(what, url)) {
467
- // Report the error.
468
- await serveError({message: 'ERROR: Page has already been tested'}, response, true);
469
- }
470
- // Otherwise, i.e. if no report on the page is available:
471
- else {
472
- // Serve headers for a response.
427
+ // Otherwise, i.e. if it is not for the MCP server:
428
+ else {
429
+ // Get the data from the request body.
430
+ const postData = await getPOSTData(request);
431
+ // If the request is a retest recommendation:
432
+ if (pageName === 'retestRec.html') {
433
+ const {why} = postData;
434
+ const [timeStamp, jobID] = pathTail.split('/');
435
+ // If the request is valid:
436
+ if (isTimeStamp(timeStamp) && isJobID(jobID) && why) {
437
+ // Serve response headers.
473
438
  setHeaders('text/html', `${pathname}${search}`, 'ultra');
474
439
  // Get the answer data.
475
- const answerData = await require(path.join(__dirname, 'testRec', 'index'))
476
- .answer(what, url, why);
440
+ const answerData = await require(path.join(__dirname, 'retestRec', 'index'))
441
+ .answer(pathTail, why);
477
442
  // If they are valid:
478
443
  if (answerData.status === 'ok') {
479
444
  // Serve the answer page.
@@ -485,265 +450,300 @@ const requestHandler = async (request, response) => {
485
450
  await serveError({message: answerData.error}, response, true);
486
451
  }
487
452
  }
453
+ // Otherwise, i.e. if the request is invalid:
454
+ else {
455
+ // Report the error.
456
+ await serveError({message: 'ERROR: Invalid retest recommendation'}, response, true);
457
+ }
488
458
  }
489
- // Otherwise, i.e. if the request is invalid:
490
- else {
491
- // Report the error.
492
- await serveError({message: 'ERROR: Invalid test recommendation'}, response, true);
493
- }
494
- }
495
- // Otherwise, if it is an action on a test or retest recommendation:
496
- else if (pageName === 'recAction.html') {
497
- const {target, authCode} = postData;
498
- const [url, what] = target.split('\t');
499
- // If the request is valid:
500
- if (url.startsWith('https://') && authCode === process.env.AUTH_CODE) {
501
- // Set the non-location headers for a response.
502
- setHeaders('text/html', null, 'ultra');
503
- // If the request is an approval:
504
- if (what) {
505
- // Set a location header for a response.
506
- response.setHeader('content-location', `${pathname}${search}`);
507
- // Get the answer data.
508
- const answerData = await require(path.join(__dirname, 'testOrder', 'index'))
509
- .answer(url, what, authCode);
510
- // If the answer data are valid:
511
- if (answerData.status === 'ok') {
512
- // Serve the answer page.
513
- response.end(answerData.answerPage);
459
+ // Otherwise, if it is a test recommendation:
460
+ else if (pageName === 'testRec.html') {
461
+ const {what, url, why} = postData;
462
+ // If the request is valid:
463
+ if (what && url.startsWith('https://') && why) {
464
+ // If a report on the page is already available:
465
+ if (await isReportAvailable(what, url)) {
466
+ // Report the error.
467
+ await serveError({message: 'ERROR: Page has already been tested'}, response, true);
514
468
  }
515
- // Otherwise, i.e. if they are invalid:
469
+ // Otherwise, i.e. if no report on the page is available:
516
470
  else {
517
- // Report the error.
518
- await serveError({message: answerData.error}, response, true);
471
+ // Serve headers for a response.
472
+ setHeaders('text/html', `${pathname}${search}`, 'ultra');
473
+ // Get the answer data.
474
+ const answerData = await require(path.join(__dirname, 'testRec', 'index'))
475
+ .answer(what, url, why);
476
+ // If they are valid:
477
+ if (answerData.status === 'ok') {
478
+ // Serve the answer page.
479
+ response.end(answerData.answerPage);
480
+ }
481
+ // Otherwise, i.e. if they are invalid:
482
+ else {
483
+ // Report the error.
484
+ await serveError({message: answerData.error}, response, true);
485
+ }
519
486
  }
520
487
  }
521
- // Otherwise, i.e. if it is a rejection:
488
+ // Otherwise, i.e. if the request is invalid:
522
489
  else {
523
- // Get the recommendations.
524
- const recs = await getRecs();
525
- // Delete the rejected URL.
526
- delete recs[url];
527
- // Save the revised recommendations.
528
- await fs.writeFile(path.join(__dirname, 'jobs', 'recs.json'), getJSON(recs));
529
- // Set a location header for a response.
530
- response.setHeader('content-location', '/recActionForm.html');
531
- // Get the answer data.
532
- const answerData = await require(path.join(__dirname, 'recActionForm', 'index')).answer();
533
- // Serve the test-order form.
534
- response.end(answerData.answerPage);
490
+ // Report the error.
491
+ await serveError({message: 'ERROR: Invalid test recommendation'}, response, true);
535
492
  }
536
493
  }
537
- // Otherwise, i.e. if the request is invalid:
538
- else {
539
- // Report the error.
540
- await serveError({message: 'ERROR: Invalid test order'}, response, true);
541
- }
542
- }
543
- // Otherwise, if it is a reannotation order:
544
- else if (pageName === 'reannotate.html') {
545
- const {authCode} = postData;
546
- // Set headers for a response.
547
- setHeaders('text/html', `${pathname}${search}`, 'ultra');
548
- // Get the answer data.
549
- const answerData = await require(path.join(__dirname, 'reannotate', 'index'))
550
- .answer(authCode);
551
- // If the answer data are valid:
552
- if (answerData.status === 'ok') {
553
- // Serve the answer page.
554
- response.end(answerData.answerPage);
555
- }
556
- // Otherwise, i.e. if they are invalid:
557
- else {
558
- // Report the error.
559
- await serveError({message: answerData.error}, response, true);
494
+ // Otherwise, if it is an action on a test or retest recommendation:
495
+ else if (pageName === 'recAction.html') {
496
+ const {target, authCode} = postData;
497
+ const [url, what] = target.split('\t');
498
+ // If the request is valid:
499
+ if (url.startsWith('https://') && authCode === process.env.AUTH_CODE) {
500
+ // Set the non-location headers for a response.
501
+ setHeaders('text/html', null, 'ultra');
502
+ // If the request is an approval:
503
+ if (what) {
504
+ // Set a location header for a response.
505
+ response.setHeader('content-location', `${pathname}${search}`);
506
+ // Get the answer data.
507
+ const answerData = await require(path.join(__dirname, 'testOrder', 'index'))
508
+ .answer(url, what, authCode);
509
+ // If the answer data are valid:
510
+ if (answerData.status === 'ok') {
511
+ // Serve the answer page.
512
+ response.end(answerData.answerPage);
513
+ }
514
+ // Otherwise, i.e. if they are invalid:
515
+ else {
516
+ // Report the error.
517
+ await serveError({message: answerData.error}, response, true);
518
+ }
519
+ }
520
+ // Otherwise, i.e. if it is a rejection:
521
+ else {
522
+ // Get the recommendations.
523
+ const recs = await getRecs();
524
+ // Delete the rejected URL.
525
+ delete recs[url];
526
+ // Save the revised recommendations.
527
+ await fs.writeFile(path.join(__dirname, 'jobs', 'recs.json'), getJSON(recs));
528
+ // Set a location header for a response.
529
+ response.setHeader('content-location', '/recActionForm.html');
530
+ // Get the answer data.
531
+ const answerData = await require(path.join(__dirname, 'recActionForm', 'index')).answer();
532
+ // Serve the test-order form.
533
+ response.end(answerData.answerPage);
534
+ }
535
+ }
536
+ // Otherwise, i.e. if the request is invalid:
537
+ else {
538
+ // Report the error.
539
+ await serveError({message: 'ERROR: Invalid test order'}, response, true);
540
+ }
560
541
  }
561
- }
562
- // Otherwise, if it is a WCAG map renewal:
563
- else if (pageName === 'wcagRenew.html') {
564
- const {authCode} = postData;
565
- // Set headers for a response.
566
- setHeaders('text/html', `${pathname}${search}`, 'low');
567
- // Get the answer data.
568
- const answerData = await require(path.join(__dirname, 'wcagRenew', 'index'))
569
- .answer(authCode);
570
- // If the answer data are valid:
571
- if (answerData.status === 'ok') {
572
- // Serve the answer page.
573
- response.end(answerData.answerPage);
542
+ // Otherwise, if it is a reannotation order:
543
+ else if (pageName === 'reannotate.html') {
544
+ const {authCode} = postData;
545
+ // Set headers for a response.
546
+ setHeaders('text/html', `${pathname}${search}`, 'ultra');
547
+ // Get the answer data.
548
+ const answerData = await require(path.join(__dirname, 'reannotate', 'index'))
549
+ .answer(authCode);
550
+ // If the answer data are valid:
551
+ if (answerData.status === 'ok') {
552
+ // Serve the answer page.
553
+ response.end(answerData.answerPage);
554
+ }
555
+ // Otherwise, i.e. if they are invalid:
556
+ else {
557
+ // Report the error.
558
+ await serveError({message: answerData.error}, response, true);
559
+ }
574
560
  }
575
- // Otherwise, i.e. if they are invalid:
576
- else {
577
- // Report the error.
578
- await serveError({message: answerData.error}, response, true);
561
+ // Otherwise, if it is a WCAG map renewal:
562
+ else if (pageName === 'wcagRenew.html') {
563
+ const {authCode} = postData;
564
+ // Set headers for a response.
565
+ setHeaders('text/html', `${pathname}${search}`, 'low');
566
+ // Get the answer data.
567
+ const answerData = await require(path.join(__dirname, 'wcagRenew', 'index'))
568
+ .answer(authCode);
569
+ // If the answer data are valid:
570
+ if (answerData.status === 'ok') {
571
+ // Serve the answer page.
572
+ response.end(answerData.answerPage);
573
+ }
574
+ // Otherwise, i.e. if they are invalid:
575
+ else {
576
+ // Report the error.
577
+ await serveError({message: answerData.error}, response, true);
578
+ }
579
579
  }
580
- }
581
- // Otherwise, if it is a request from an agent:
582
- else if (pageName === 'api') {
583
- // Get the segments of the path after api.
584
- const segments = pathTail.split('/');
585
- // If the first segment is the ID of the Testaro agent and the agent is authenticated:
586
- if (segments[0] === testaroAgent && postData.agentPW === testaroAgentPW) {
587
- const agentID = segments[0];
588
- // Get the requested service from the path.
589
- const service = segments[1];
590
- // If the service is job assignment:
591
- if (service === 'job') {
592
- let clean = true;
593
- const messageStart = `Testaro agent ${agentID} requested a job, `;
594
- const jobNames = await getJobNames();
595
- const claimedJobNames = jobNames.claimed;
596
- // For each claimed job:
597
- for (const jobName of claimedJobNames) {
598
- const job = await getObject(path.join(jobsPath, 'claimed', jobName));
599
- const {id, sources} = job;
600
- const {agent} = sources;
601
- // If its assignee is the agent:
602
- if (agent === agentID) {
603
- const messageEnd = `but has not completed job ${id}`;
604
- // Report this.
605
- await serveError({message: `${messageStart}${messageEnd}`}, response, false);
606
- // Reclassify the job as failed.
607
- await fs.rename(
608
- path.join(claimedPath, jobName), path.join(failedPath, jobName)
609
- );
610
- clean = false;
611
- // Stop checking claimed jobs.
612
- break;
580
+ // Otherwise, if it is a request from an agent:
581
+ else if (pageName === 'api') {
582
+ // Get the segments of the path after api.
583
+ const segments = pathTail.split('/');
584
+ // If the first segment is the ID of the Testaro agent and the agent is authenticated:
585
+ if (segments[0] === testaroAgent && postData.agentPW === testaroAgentPW) {
586
+ const agentID = segments[0];
587
+ // Get the requested service from the path.
588
+ const service = segments[1];
589
+ // If the service is job assignment:
590
+ if (service === 'job') {
591
+ let clean = true;
592
+ const messageStart = `Testaro agent ${agentID} requested a job, `;
593
+ const jobNames = await getJobNames();
594
+ const claimedJobNames = jobNames.claimed;
595
+ // For each claimed job:
596
+ for (const jobName of claimedJobNames) {
597
+ const job = await getObject(path.join(jobsPath, 'claimed', jobName));
598
+ const {id, sources} = job;
599
+ const {agent} = sources;
600
+ // If its assignee is the agent:
601
+ if (agent === agentID) {
602
+ const messageEnd = `but has not completed job ${id}`;
603
+ // Report this.
604
+ await serveError({message: `${messageStart}${messageEnd}`}, response, false);
605
+ // Reclassify the job as failed.
606
+ await fs.rename(
607
+ path.join(claimedPath, jobName), path.join(failedPath, jobName)
608
+ );
609
+ clean = false;
610
+ // Stop checking claimed jobs.
611
+ break;
612
+ }
613
+ }
614
+ // If no aborted-job error was found for the agent:
615
+ if (clean) {
616
+ const queuedJobNames = jobNames.queue;
617
+ // If any jobs are queued:
618
+ if (queuedJobNames.length) {
619
+ const oldestJobName = queuedJobNames[0];
620
+ // Get the first one.
621
+ const firstJob = await getObject(path.join(queuePath, oldestJobName));
622
+ // Add the agent ID to the job.
623
+ firstJob.sources.agent = agentID;
624
+ console.log(
625
+ `Job ${firstJob.id} (${firstJob.target.what}) is being sent to the agent.`
626
+ );
627
+ // Assign the job to the agent.
628
+ response.writeHead(200, {
629
+ 'content-type': 'application/json; charset=utf-8'
630
+ });
631
+ response.end(JSON.stringify(firstJob));
632
+ const messageEnd
633
+ = `and job ${firstJob.id} (${firstJob.target.what}) was assigned to the agent`;
634
+ console.log(`${messageStart}${messageEnd}`);
635
+ // Move the job from the queue to the claimed-jobs directory.
636
+ await fs.rename(
637
+ path.join(queuePath, oldestJobName), path.join(claimedPath, oldestJobName)
638
+ );
639
+ }
640
+ // Otherwise, i.e. if no jobs are queued:
641
+ else {
642
+ response.writeHead(200, {
643
+ 'content-type': 'application/json; charset=utf-8'
644
+ });
645
+ // Send a no-jobs response to the agent.
646
+ response.end(JSON.stringify({}));
647
+ const messageEnd = 'but no job was in the queue';
648
+ console.log(`${messageStart}${messageEnd}`);
649
+ }
613
650
  }
614
651
  }
615
- // If no aborted-job error was found for the agent:
616
- if (clean) {
617
- const queuedJobNames = jobNames.queue;
618
- // If any jobs are queued:
619
- if (queuedJobNames.length) {
620
- const oldestJobName = queuedJobNames[0];
621
- // Get the first one.
622
- const firstJob = await getObject(path.join(queuePath, oldestJobName));
623
- // Add the agent ID to the job.
624
- firstJob.sources.agent = agentID;
625
- console.log(
626
- `Job ${firstJob.id} (${firstJob.target.what}) is being sent to the agent.`
627
- );
628
- // Assign the job to the agent.
629
- response.writeHead(200, {
630
- 'content-type': 'application/json; charset=utf-8'
631
- });
632
- response.end(JSON.stringify(firstJob));
633
- const messageEnd
634
- = `and job ${firstJob.id} (${firstJob.target.what}) was assigned to the agent`;
635
- console.log(`${messageStart}${messageEnd}`);
636
- // Move the job from the queue to the claimed-jobs directory.
637
- await fs.rename(
638
- path.join(queuePath, oldestJobName), path.join(claimedPath, oldestJobName)
639
- );
652
+ // Otherwise, if the service is report acquisition:
653
+ else if (service === 'report') {
654
+ const {report} = postData;
655
+ const {id, target} = report;
656
+ const {what, url} = target;
657
+ const [timeStamp, jobID] = id?.split('-') ?? ['', ''];
658
+ // If the request is valid:
659
+ if (id && isTimeStamp(timeStamp) && isJobID(jobID) && what && url) {
660
+ // Acknowledge receipt.
661
+ response.setHeader('content-type', 'application/json; charset=utf-8');
662
+ response.end(JSON.stringify({status: 'ok'}));
663
+ console.log(`Testaro report ${id} was received from Testaro agent ${agentID}`);
664
+ const [timeStamp, jobID] = id.split('-');
665
+ // Save the report.
666
+ await fs.writeFile(getReportPath(timeStamp, jobID), getJSON(report));
667
+ // Create a log for the report.
668
+ const log = {
669
+ what,
670
+ url
671
+ };
672
+ // Save the log.
673
+ await fs.writeFile(getLogPath(timeStamp, jobID), getJSON(log));
674
+ // Annotate the report and mark it as annotated in the log.
675
+ await annotateReport(ruleIDs, timeStamp, jobID);
676
+ console.log(`Testaro report ${id} was annotated, saved, and logged`);
677
+ // Check the monetary balances and send alerts if nearing exhaustion.
678
+ await checkBalancesForAlerts(report);
679
+ // Delete the job.
680
+ await fs.unlink(path.join(claimedPath, `${id}.json`));
681
+ console.log(`Completed job ${id} deleted`);
640
682
  }
641
- // Otherwise, i.e. if no jobs are queued:
683
+ // Otherwise, i.e. if the request is invalid:
642
684
  else {
643
- response.writeHead(200, {
644
- 'content-type': 'application/json; charset=utf-8'
645
- });
646
- // Send a no-jobs response to the agent.
647
- response.end(JSON.stringify({}));
648
- const messageEnd = 'but no job was in the queue';
649
- console.log(`${messageStart}${messageEnd}`);
685
+ await serveError({message: 'ERROR: Report invalid'}, response, false);
650
686
  }
651
687
  }
688
+ // Otherwise, if the service is not valid:
689
+ else {
690
+ await serveError(
691
+ {message: 'ERROR: Invalid service request from Testaro agent'}, response, false
692
+ );
693
+ }
652
694
  }
653
- // Otherwise, if the service is report acquisition:
654
- else if (service === 'report') {
655
- const {report} = postData;
656
- const {id, target} = report;
657
- const {what, url} = target;
658
- const [timeStamp, jobID] = id?.split('-') ?? ['', ''];
659
- // If the request is valid:
660
- if (id && isTimeStamp(timeStamp) && isJobID(jobID) && what && url) {
661
- // Acknowledge receipt.
662
- response.setHeader('content-type', 'application/json; charset=utf-8');
663
- response.end(JSON.stringify({status: 'ok'}));
664
- console.log(`Testaro report ${id} was received from Testaro agent ${agentID}`);
665
- const [timeStamp, jobID] = id.split('-');
666
- // Save the report.
667
- await fs.writeFile(getReportPath(timeStamp, jobID), getJSON(report));
668
- // Create a log for the report.
669
- const log = {
670
- what,
671
- url
672
- };
673
- // Save the log.
674
- await fs.writeFile(getLogPath(timeStamp, jobID), getJSON(log));
675
- // Annotate the report and mark it as annotated in the log.
676
- await annotateReport(ruleIDs, timeStamp, jobID);
677
- console.log(`Testaro report ${id} was annotated, saved, and logged`);
678
- // Check the monetary balances and send alerts if nearing exhaustion.
679
- await checkBalancesForAlerts(report);
680
- // Delete the job.
681
- await fs.unlink(path.join(claimedPath, `${id}.json`));
682
- console.log(`Completed job ${id} deleted`);
695
+ // Otherwise, if the first segment is the test recommendation service:
696
+ else if (segments[0] === 'testRecForm') {
697
+ const {what, url, why} = postData;
698
+ // If the payload is a valid test recommendation:
699
+ if (what && isURL(url) && why) {
700
+ // If a report on the page is already available:
701
+ if (await isReportAvailable(what, url)) {
702
+ // Report this.
703
+ await serveError({message: 'ERROR: A report on the page is already available'}, response, false);
704
+ }
705
+ // Otherwise, i.e. if no report on the page is available:
706
+ else {
707
+ // Process the recommendation and get the response data.
708
+ const responseData = await require(path.join(__dirname, 'testRecForm', 'api'))
709
+ .response(what, url, why);
710
+ // Send them.
711
+ setHeaders('application/json', null, 'ultra');
712
+ response.end(JSON.stringify(responseData));
713
+ }
683
714
  }
684
- // Otherwise, i.e. if the request is invalid:
715
+ // Otherwise, i.e. if it is not a valid test recommendation:
685
716
  else {
686
- await serveError({message: 'ERROR: Report invalid'}, response, false);
717
+ // Report this.
718
+ await serveError({message: 'ERROR: Invalid test recommendation'}, response, false);
687
719
  }
688
720
  }
689
- // Otherwise, if the service is not valid:
721
+ // Otherwise, i.e. if the request is invalid:
690
722
  else {
723
+ // Report this.
691
724
  await serveError(
692
- {message: 'ERROR: Invalid service request from Testaro agent'}, response, false
725
+ {message: 'ERROR: Invalid API request'}, response, false
693
726
  );
694
727
  }
695
728
  }
696
- // Otherwise, if the first segment is the test recommendation service:
697
- else if (segments[0] === 'testRecForm') {
698
- const {what, url, why} = postData;
699
- // If the payload is a valid test recommendation:
700
- if (what && isURL(url) && why) {
701
- // If a report on the page is already available:
702
- if (await isReportAvailable(what, url)) {
703
- // Report this.
704
- await serveError({message: 'ERROR: A report on the page is already available'}, response, false);
705
- }
706
- // Otherwise, i.e. if no report on the page is available:
707
- else {
708
- // Process the recommendation and get the response data.
709
- const responseData = await require(path.join(__dirname, 'testRecForm', 'api'))
710
- .response(what, url, why);
711
- // Send them.
712
- setHeaders('application/json', null, 'ultra');
713
- response.end(JSON.stringify(responseData));
714
- }
729
+ // Otherwise, if it is a tutorial comment:
730
+ else if (pageName === 'tutorialComment.html') {
731
+ const {content} = postData;
732
+ setHeaders('application/json', null, 'low');
733
+ const answerData = await require(path.join(__dirname, 'tutorial', 'index')).saveComment(content);
734
+ if (answerData.status === 'ok') {
735
+ response.end(JSON.stringify({status: 'ok'}));
715
736
  }
716
- // Otherwise, i.e. if it is not a valid test recommendation:
717
737
  else {
718
- // Report this.
719
- await serveError({message: 'ERROR: Invalid test recommendation'}, response, false);
738
+ response.statusCode = 400;
739
+ response.end(JSON.stringify({status: 'error', message: answerData.error}));
720
740
  }
721
741
  }
722
- // Otherwise, i.e. if the request is invalid:
742
+ // Otherwise, i.e. if it is any other POST request:
723
743
  else {
724
- // Report this.
725
- await serveError(
726
- {message: 'ERROR: Invalid API request'}, response, false
727
- );
728
- }
729
- }
730
- // Otherwise, if it is a tutorial comment:
731
- else if (pageName === 'tutorialComment.html') {
732
- const {content} = postData;
733
- setHeaders('application/json', null, 'low');
734
- const answerData = await require(path.join(__dirname, 'tutorial', 'index')).saveComment(content);
735
- if (answerData.status === 'ok') {
736
- response.end(JSON.stringify({status: 'ok'}));
744
+ // Report its invalidity.
745
+ await serveError({message: 'ERROR: Invalid POST request'}, response, true);
737
746
  }
738
- else {
739
- response.statusCode = 400;
740
- response.end(JSON.stringify({status: 'error', message: answerData.error}));
741
- }
742
- }
743
- // Otherwise, i.e. if it is any other POST request:
744
- else {
745
- // Report its invalidity.
746
- await serveError({message: 'ERROR: Invalid POST request'}, response, true);
747
747
  }
748
748
  }
749
749
  // Otherwise, i.e. if it is neither a GET nor a POST request: