Skip to content

Commit bd3d619

Browse files
committed
Reinstated / fixed a lot of API tests
1 parent 78ef1c6 commit bd3d619

File tree

7 files changed

+165
-102
lines changed

7 files changed

+165
-102
lines changed

gulpfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ gulp.task('midwayTest', function(done) {
105105
gulp.task('apiTest', function () {
106106
return gulp.src('test/api/API-Spec.js', {read: false})
107107
// gulp-mocha needs filepaths so you can't have any plugins before it
108-
.pipe(require('gulp-mocha')({reporter: 'dot'}));
108+
.pipe(require('gulp-mocha')({reporter: 'dot', 'forbid-only': true}));
109109
});
110110

111111
gulp.task('saveDebug', function () {

src/server/data_form.ts

Lines changed: 92 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import ListField = fngServer.ListField;
66
import FngOptions = fngServer.FngOptions;
77
import IFngPlugin = fngServer.IFngPlugin;
88
import IInternalSearchResult = fngServer.IInternalSearchResult;
9+
import ISearchResultFormatter = fngServer.ISearchResultFormatter;
910
import Path = fngServer.Path;
1011

1112
// This part of forms-angular borrows _very_ heavily from https://github.com/Alexandre-Strzelewicz/angular-bridge
@@ -310,96 +311,100 @@ export class FormsAngular {
310311
}
311312

312313
let handleSearchResultsFromIndex = function (err, docs, item, cb) {
313-
if (!err && docs && docs.length > 0) {
314-
async.map(docs, async function (aDoc, cbdoc) {
315-
// Do we already have them in the list?
316-
let thisId: string = aDoc._id.toString(),
317-
resultObject: IInternalSearchResult,
318-
resultPos: number;
319-
320-
function handleResultsInList() {
321-
if (multiMatchPossible) {
322-
resultObject.matched = resultObject.matched || [];
323-
324-
// record the index of string that matched, so we don't count it against another field
325-
for (let i = 0; i < searchStrings.length; i++) {
326-
if (aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
327-
resultObject.matched.push(i);
328-
break;
329-
}
314+
315+
function handleSingleSearchResult(aDoc: Document, cbdoc) {
316+
let thisId: string = aDoc._id.toString(),
317+
resultObject: IInternalSearchResult,
318+
resultPos: number;
319+
320+
function handleResultsInList() {
321+
if (multiMatchPossible) {
322+
resultObject.matched = resultObject.matched || [];
323+
324+
// record the index of string that matched, so we don't count it against another field
325+
for (let i = 0; i < searchStrings.length; i++) {
326+
if (aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
327+
resultObject.matched.push(i);
328+
break;
330329
}
331330
}
331+
}
332332

333-
resultObject.searchImportance = item.resource.options.searchImportance || 99;
334-
if (item.resource.options.localisationData) {
335-
resultObject.resource = translate(resultObject.resource, item.resource.options.localisationData, "resource");
336-
resultObject.resourceText = translate(resultObject.resourceText, item.resource.options.localisationData, "resourceText");
337-
resultObject.resourceTab = translate(resultObject.resourceTab, item.resource.options.localisationData, "resourceTab");
338-
}
339-
results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
340-
cbdoc(null);
333+
resultObject.searchImportance = item.resource.options.searchImportance || 99;
334+
if (item.resource.options.localisationData) {
335+
resultObject.resource = translate(resultObject.resource, item.resource.options.localisationData, "resource");
336+
resultObject.resourceText = translate(resultObject.resourceText, item.resource.options.localisationData, "resourceText");
337+
resultObject.resourceTab = translate(resultObject.resourceTab, item.resource.options.localisationData, "resourceTab");
341338
}
339+
results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
340+
cbdoc(null);
341+
}
342342

343-
for (resultPos = results.length - 1; resultPos >= 0; resultPos--) {
344-
if (results[resultPos].id.toString() === thisId) {
345-
break;
346-
}
343+
// Do we already have them in the list?
344+
for (resultPos = results.length - 1; resultPos >= 0; resultPos--) {
345+
if (results[resultPos].id.toString() === thisId) {
346+
break;
347347
}
348-
if (resultPos >= 0) {
349-
resultObject = Object.assign({}, results[resultPos]);
350-
// If they have already matched then improve their weighting
351-
if (multiMatchPossible) {
352-
// record the index of string that matched, so we don't count it against another field
353-
for (let i = 0; i < searchStrings.length; i++) {
354-
if (!resultObject.matched.includes(i) && aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
355-
resultObject.matched.push(i);
356-
resultObject.addHits = Math.max((resultObject.addHits || 9) - 1, 0);
357-
// remove it from current position
358-
results.splice(resultPos, 1);
359-
// and re-insert where appropriate
360-
results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
361-
break;
362-
}
348+
}
349+
if (resultPos >= 0) {
350+
resultObject = Object.assign({}, results[resultPos]);
351+
// If they have already matched then improve their weighting
352+
if (multiMatchPossible) {
353+
// record the index of string that matched, so we don't count it against another field
354+
for (let i = 0; i < searchStrings.length; i++) {
355+
if (!resultObject.matched.includes(i) && aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
356+
resultObject.matched.push(i);
357+
resultObject.addHits = Math.max((resultObject.addHits || 9) - 1, 0);
358+
// remove it from current position
359+
results.splice(resultPos, 1);
360+
// and re-insert where appropriate
361+
results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
362+
break;
363363
}
364364
}
365-
cbdoc(null);
366-
} else {
367-
// Otherwise add them new...
368-
let addHits;
369-
if (multiMatchPossible)
370-
// If they match the whole search phrase in one index they get smaller addHits (so they sort higher)
371-
if (aDoc[item.field].toLowerCase().indexOf(searchFor) === 0) {
372-
addHits = 7;
373-
}
365+
}
366+
cbdoc(null);
367+
} else {
368+
// Otherwise add them new...
369+
let addHits;
370+
if (multiMatchPossible)
371+
// If they match the whole search phrase in one index they get smaller addHits (so they sort higher)
372+
if (aDoc[item.field].toLowerCase().indexOf(searchFor) === 0) {
373+
addHits = 7;
374+
}
374375

375-
// Use special listings format if defined
376-
let specialListingFormat = item.resource.options.searchResultFormat;
377-
if (specialListingFormat) {
378-
resultObject = await specialListingFormat.apply(aDoc);
379-
resultObject.addHits = addHits;
380-
handleResultsInList();
381-
} else {
382-
that.getListFields(item.resource, aDoc, function (err, description) {
383-
if (err) {
384-
cbdoc(err);
385-
} else {
386-
(resultObject as any) = {
387-
id: aDoc._id,
388-
weighting: 9999,
389-
addHits,
390-
text: description
391-
};
392-
if (resourceCount > 1 || includeResourceInResults) {
393-
resultObject.resource = resultObject.resourceText = item.resource.resourceName;
394-
}
395-
handleResultsInList();
396-
}
376+
// Use special listings format if defined
377+
let specialListingFormat: ISearchResultFormatter = item.resource.options.searchResultFormat;
378+
if (specialListingFormat) {
379+
specialListingFormat.apply(aDoc)
380+
.then((resultObj) => {
381+
resultObject = resultObj;
382+
resultObject.addHits = addHits;
383+
handleResultsInList();
397384
});
398-
}
385+
} else {
386+
that.getListFields(item.resource, aDoc, function (err, description) {
387+
if (err) {
388+
cbdoc(err);
389+
} else {
390+
(resultObject as any) = {
391+
id: aDoc._id,
392+
weighting: 9999,
393+
addHits,
394+
text: description
395+
};
396+
if (resourceCount > 1 || includeResourceInResults) {
397+
resultObject.resource = resultObject.resourceText = item.resource.resourceName;
398+
}
399+
handleResultsInList();
400+
}
401+
});
399402
}
400-
}, function (err) {
401-
cb(err);
402-
});
403+
}
404+
}
405+
406+
if (!err && docs && docs.length > 0) {
407+
async.map(docs, handleSingleSearchResult, cb);
403408
} else {
404409
cb(err);
405410
}
@@ -541,7 +546,7 @@ export class FormsAngular {
541546
}
542547
}
543548
outPath[fld].options = outPath[fld].options || {};
544-
for (var override in schema[fld]) {
549+
for (const override in schema[fld]) {
545550
if (schema[fld].hasOwnProperty(override)) {
546551
if (override.slice(0, 1) !== '_') {
547552
if (schema[fld].hasOwnProperty(override)) {
@@ -668,7 +673,7 @@ export class FormsAngular {
668673
reportSchema = JSON.parse(req.query.r);
669674
break;
670675
default:
671-
return self.renderError(new Error('Invalid "r" parameter'), null, req, res, next);
676+
return self.renderError( new Error('Invalid "r" parameter'), null, req, res);
672677
}
673678
} else {
674679
let fields = {};
@@ -695,7 +700,7 @@ export class FormsAngular {
695700

696701
self.reportInternal(req, req.resource, schemaCopy, function (err, result) {
697702
if (err) {
698-
self.renderError(err, null, req, res, next);
703+
self.renderError(err, null, req, res);
699704
} else {
700705
res.send(result);
701706
}
@@ -912,8 +917,8 @@ export class FormsAngular {
912917
// TODO - this ref func can probably be done away with now that list fields can have ref
913918
let j = 0;
914919
async.whilst(
915-
function () {
916-
return j < findResults.length;
920+
function (cbtest) {
921+
cbtest(null, j < findResults.length);
917922
},
918923
function (cbres) {
919924
let theResult = findResults[j];
@@ -1072,7 +1077,7 @@ export class FormsAngular {
10721077
const self = this;
10731078
this.filteredFind(req.resource, req, aggregationParam, findParam, projectParam, orderParam, limitParam, skipParam, function (err, docs) {
10741079
if (err) {
1075-
return self.renderError(err, null, req, res, next);
1080+
return self.renderError(err, null, req, res);
10761081
} else {
10771082
res.send(docs);
10781083
}
@@ -1150,7 +1155,7 @@ export class FormsAngular {
11501155
function doAggregation(queryObj, cb) {
11511156
if (aggregationParam) {
11521157
aggregationParam = that.sanitisePipeline(aggregationParam, hiddenFields, queryObj);
1153-
resource.model.aggregate(aggregationParam, function (err, aggregationResults) {
1158+
void resource.model.aggregate(aggregationParam, function (err, aggregationResults) {
11541159
if (err) {
11551160
throw err;
11561161
} else {
@@ -1291,7 +1296,7 @@ export class FormsAngular {
12911296
} else {
12921297
crit = idSel;
12931298
}
1294-
cb(null, resource.model.findOne(crit).select(that.generateProjection(hiddenFields, req.query.p)));
1299+
cb(null, resource.model.findOne(crit).select(that.generateProjection(hiddenFields, req.query?.p)));
12951300
}
12961301
});
12971302
};

src/server/index.d.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ declare module fngServer {
3131
[pathName: string]: Path;
3232
}
3333

34+
export type ISearchResultFormatter = () => Promise<ISearchResult>;
35+
3436
export interface ResourceOptions {
3537
suppressDeprecatedMessage?: boolean;
3638
onRemove?: (doc, req, cb) => void;
@@ -40,7 +42,7 @@ declare module fngServer {
4042
findFunc?: (req, cb) => void,
4143
getOrgCriteria?: (userOrganisation: string) => Promise<any>
4244
idIsList?: IIdIsList,
43-
searchResultFormat?: ISearchResult,
45+
searchResultFormat?: ISearchResultFormatter,
4446
searchOrder?: any,
4547
listOrder?: any,
4648
onAccess?: (req, cb) => void,
@@ -62,12 +64,15 @@ declare module fngServer {
6264
callback: (err: Error, docs?: any[]) => void
6365
) => void;
6466

65-
interface Resource {
66-
resourceName: string;
67+
interface ResourceExport {
6768
model?: Model<any>; // TODO TS Get rid of the ? here
6869
options?: ResourceOptions;
6970
}
7071

72+
interface Resource extends ResourceExport {
73+
resourceName: string;
74+
}
75+
7176
interface ListParams {
7277
ref: Boolean; // The object is this a lookup?
7378
}

0 commit comments

Comments
 (0)