|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
|
|
const assert = require('assert');
|
|
|
|
const async = require('async');
|
|
|
|
const request = require('request');
|
|
|
|
const nconf = require('nconf');
|
|
|
|
|
|
|
|
const db = require('./mocks/databasemock');
|
|
|
|
const topics = require('../src/topics');
|
|
|
|
const categories = require('../src/categories');
|
|
|
|
const user = require('../src/user');
|
|
|
|
const search = require('../src/search');
|
|
|
|
const privileges = require('../src/privileges');
|
|
|
|
|
|
|
|
describe('Search', () => {
|
|
|
|
let phoebeUid;
|
|
|
|
let gingerUid;
|
|
|
|
|
|
|
|
let topic1Data;
|
|
|
|
let topic2Data;
|
|
|
|
let post1Data;
|
|
|
|
let post2Data;
|
|
|
|
let post3Data;
|
|
|
|
let cid1;
|
|
|
|
let cid2;
|
|
|
|
let cid3;
|
|
|
|
|
|
|
|
before((done) => {
|
|
|
|
async.waterfall([
|
|
|
|
function (next) {
|
|
|
|
async.series({
|
|
|
|
phoebe: function (next) {
|
|
|
|
user.create({ username: 'phoebe' }, next);
|
|
|
|
},
|
|
|
|
ginger: function (next) {
|
|
|
|
user.create({ username: 'ginger' }, next);
|
|
|
|
},
|
|
|
|
category1: function (next) {
|
|
|
|
categories.create({
|
|
|
|
name: 'Test Category',
|
|
|
|
description: 'Test category created by testing script',
|
|
|
|
}, next);
|
|
|
|
},
|
|
|
|
category2: function (next) {
|
|
|
|
categories.create({
|
|
|
|
name: 'Test Category',
|
|
|
|
description: 'Test category created by testing script',
|
|
|
|
}, next);
|
|
|
|
},
|
|
|
|
}, next);
|
|
|
|
},
|
|
|
|
function (results, next) {
|
|
|
|
phoebeUid = results.phoebe;
|
|
|
|
gingerUid = results.ginger;
|
|
|
|
cid1 = results.category1.cid;
|
|
|
|
cid2 = results.category2.cid;
|
|
|
|
|
|
|
|
async.waterfall([
|
|
|
|
function (next) {
|
|
|
|
categories.create({
|
|
|
|
name: 'Child Test Category',
|
|
|
|
description: 'Test category created by testing script',
|
|
|
|
parentCid: cid2,
|
|
|
|
}, next);
|
|
|
|
},
|
|
|
|
function (category, next) {
|
|
|
|
cid3 = category.cid;
|
|
|
|
topics.post({
|
|
|
|
uid: phoebeUid,
|
|
|
|
cid: cid1,
|
|
|
|
title: 'nodebb mongodb bugs',
|
|
|
|
content: 'avocado cucumber apple orange fox',
|
|
|
|
tags: ['nodebb', 'bug', 'plugin', 'nodebb-plugin', 'jquery'],
|
|
|
|
}, next);
|
|
|
|
},
|
|
|
|
function (results, next) {
|
|
|
|
topic1Data = results.topicData;
|
|
|
|
post1Data = results.postData;
|
|
|
|
|
|
|
|
topics.post({
|
|
|
|
uid: gingerUid,
|
|
|
|
cid: cid2,
|
|
|
|
title: 'java mongodb redis',
|
|
|
|
content: 'avocado cucumber carrot armadillo',
|
|
|
|
tags: ['nodebb', 'bug', 'plugin', 'nodebb-plugin', 'javascript'],
|
|
|
|
}, next);
|
|
|
|
},
|
|
|
|
function (results, next) {
|
|
|
|
topic2Data = results.topicData;
|
|
|
|
post2Data = results.postData;
|
|
|
|
topics.reply({
|
|
|
|
uid: phoebeUid,
|
|
|
|
content: 'reply post apple',
|
|
|
|
tid: topic2Data.tid,
|
|
|
|
}, next);
|
|
|
|
},
|
|
|
|
function (_post3Data, next) {
|
|
|
|
post3Data = _post3Data;
|
|
|
|
setTimeout(next, 500);
|
|
|
|
},
|
|
|
|
], next);
|
|
|
|
},
|
|
|
|
], done);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should search term in titles and posts', (done) => {
|
|
|
|
const meta = require('../src/meta');
|
|
|
|
const qs = `/api/search?term=cucumber&in=titlesposts&categories[]=${cid1}&by=phoebe&replies=1&repliesFilter=atleast&sortBy=timestamp&sortDirection=desc&showAs=posts`;
|
|
|
|
privileges.global.give(['groups:search:content'], 'guests', (err) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
request({
|
|
|
|
url: nconf.get('url') + qs,
|
|
|
|
json: true,
|
|
|
|
}, (err, response, body) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
assert(body);
|
|
|
|
assert.equal(body.matchCount, 1);
|
|
|
|
assert.equal(body.posts.length, 1);
|
|
|
|
assert.equal(body.posts[0].pid, post1Data.pid);
|
|
|
|
assert.equal(body.posts[0].uid, phoebeUid);
|
|
|
|
|
|
|
|
privileges.global.rescind(['groups:search:content'], 'guests', done);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should search for a user', (done) => {
|
|
|
|
search.search({
|
|
|
|
query: 'gin',
|
|
|
|
searchIn: 'users',
|
|
|
|
}, (err, data) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
assert(data);
|
|
|
|
assert.equal(data.matchCount, 1);
|
|
|
|
assert.equal(data.users.length, 1);
|
|
|
|
assert.equal(data.users[0].uid, gingerUid);
|
|
|
|
assert.equal(data.users[0].username, 'ginger');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should search for a tag', (done) => {
|
|
|
|
search.search({
|
|
|
|
query: 'plug',
|
|
|
|
searchIn: 'tags',
|
|
|
|
}, (err, data) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
assert(data);
|
|
|
|
assert.equal(data.matchCount, 1);
|
|
|
|
assert.equal(data.tags.length, 1);
|
|
|
|
assert.equal(data.tags[0].value, 'plugin');
|
|
|
|
assert.equal(data.tags[0].score, 2);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should search for a category', async () => {
|
|
|
|
await categories.create({
|
|
|
|
name: 'foo category',
|
|
|
|
description: 'Test category created by testing script',
|
|
|
|
});
|
|
|
|
await categories.create({
|
|
|
|
name: 'baz category',
|
|
|
|
description: 'Test category created by testing script',
|
|
|
|
});
|
|
|
|
const result = await search.search({
|
|
|
|
query: 'baz',
|
|
|
|
searchIn: 'categories',
|
|
|
|
});
|
|
|
|
assert.strictEqual(result.matchCount, 1);
|
|
|
|
assert.strictEqual(result.categories[0].name, 'baz category');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should search for categories', async () => {
|
|
|
|
const socketCategories = require('../src/socket.io/categories');
|
|
|
|
let data = await socketCategories.categorySearch({ uid: phoebeUid }, { query: 'baz', parentCid: 0 });
|
|
|
|
assert.strictEqual(data[0].name, 'baz category');
|
|
|
|
data = await socketCategories.categorySearch({ uid: phoebeUid }, { query: '', parentCid: 0 });
|
|
|
|
assert.strictEqual(data.length, 5);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should fail if searchIn is wrong', (done) => {
|
|
|
|
search.search({
|
|
|
|
query: 'plug',
|
|
|
|
searchIn: '',
|
|
|
|
}, (err) => {
|
|
|
|
assert.equal(err.message, '[[error:unknown-search-filter]]');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should search with tags filter', (done) => {
|
|
|
|
search.search({
|
|
|
|
query: 'mongodb',
|
|
|
|
searchIn: 'titles',
|
|
|
|
hasTags: ['nodebb', 'javascript'],
|
|
|
|
}, (err, data) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
assert.equal(data.posts[0].tid, topic2Data.tid);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not crash if tags is not an array', (done) => {
|
|
|
|
search.search({
|
|
|
|
query: 'mongodb',
|
|
|
|
searchIn: 'titles',
|
|
|
|
hasTags: 'nodebb,javascript',
|
|
|
|
}, (err, data) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not find anything', (done) => {
|
|
|
|
search.search({
|
|
|
|
query: 'xxxxxxxxxxxxxx',
|
|
|
|
searchIn: 'titles',
|
|
|
|
}, (err, data) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
assert(Array.isArray(data.posts));
|
|
|
|
assert(!data.matchCount);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should search child categories', (done) => {
|
|
|
|
async.waterfall([
|
|
|
|
function (next) {
|
|
|
|
topics.post({
|
|
|
|
uid: gingerUid,
|
|
|
|
cid: cid3,
|
|
|
|
title: 'child category topic',
|
|
|
|
content: 'avocado cucumber carrot armadillo',
|
|
|
|
}, next);
|
|
|
|
},
|
|
|
|
function (result, next) {
|
|
|
|
search.search({
|
|
|
|
query: 'avocado',
|
|
|
|
searchIn: 'titlesposts',
|
|
|
|
categories: [cid2],
|
|
|
|
searchChildren: true,
|
|
|
|
sortBy: 'topic.timestamp',
|
|
|
|
sortDirection: 'desc',
|
|
|
|
}, next);
|
|
|
|
},
|
|
|
|
function (result, next) {
|
|
|
|
assert(result.posts.length, 2);
|
|
|
|
assert(result.posts[0].topic.title === 'child category topic');
|
|
|
|
assert(result.posts[1].topic.title === 'java mongodb redis');
|
|
|
|
next();
|
|
|
|
},
|
|
|
|
], done);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return json search data with no categories', (done) => {
|
|
|
|
const qs = '/api/search?term=cucumber&in=titlesposts&searchOnly=1';
|
|
|
|
privileges.global.give(['groups:search:content'], 'guests', (err) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
request({
|
|
|
|
url: nconf.get('url') + qs,
|
|
|
|
json: true,
|
|
|
|
}, (err, response, body) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
assert(body);
|
|
|
|
assert(body.hasOwnProperty('matchCount'));
|
|
|
|
assert(body.hasOwnProperty('pagination'));
|
|
|
|
assert(body.hasOwnProperty('pageCount'));
|
|
|
|
assert(body.hasOwnProperty('posts'));
|
|
|
|
assert(!body.hasOwnProperty('categories'));
|
|
|
|
|
|
|
|
privileges.global.rescind(['groups:search:content'], 'guests', done);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not crash without a search term', (done) => {
|
|
|
|
const qs = '/api/search';
|
|
|
|
privileges.global.give(['groups:search:content'], 'guests', (err) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
request({
|
|
|
|
url: nconf.get('url') + qs,
|
|
|
|
json: true,
|
|
|
|
}, (err, response, body) => {
|
|
|
|
assert.ifError(err);
|
|
|
|
assert(body);
|
|
|
|
assert.strictEqual(response.statusCode, 200);
|
|
|
|
privileges.global.rescind(['groups:search:content'], 'guests', done);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|