mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-03-01 01:51:18 +01:00
tag tests
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
var topics = require('../../topics');
|
||||
var utils = require('../../../public/src/utils');
|
||||
|
||||
@@ -13,9 +14,6 @@ module.exports = function (SocketTopics) {
|
||||
};
|
||||
|
||||
SocketTopics.searchAndLoadTags = function (socket, data, callback) {
|
||||
if (!data) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
topics.searchAndLoadTags(data, callback);
|
||||
};
|
||||
|
||||
@@ -26,13 +24,14 @@ module.exports = function (SocketTopics) {
|
||||
|
||||
var start = parseInt(data.after, 10);
|
||||
var stop = start + 99;
|
||||
|
||||
topics.getTags(start, stop, function (err, tags) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
topics.getTags(start, stop, next);
|
||||
},
|
||||
function (tags, next) {
|
||||
tags = tags.filter(Boolean);
|
||||
next(null, {tags: tags, nextStart: stop + 1});
|
||||
}
|
||||
tags = tags.filter(Boolean);
|
||||
callback(null, {tags: tags, nextStart: stop + 1});
|
||||
});
|
||||
], callback);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -178,30 +178,30 @@ module.exports = function (Topics) {
|
||||
var sets = tids.map(function (tid) {
|
||||
return 'topic:' + tid + ':tags';
|
||||
});
|
||||
var uniqueTopicTags;
|
||||
var topicTags;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getSetsMembers(sets, next);
|
||||
},
|
||||
function (_topicTags, next) {
|
||||
topicTags = _topicTags;
|
||||
uniqueTopicTags = _.uniq(_.flatten(topicTags));
|
||||
|
||||
db.getSetsMembers(sets, function (err, topicTags) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var uniqueTopicTags = _.uniq(_.flatten(topicTags));
|
||||
|
||||
var tags = uniqueTopicTags.map(function (tag) {
|
||||
return {value: tag};
|
||||
});
|
||||
|
||||
async.parallel({
|
||||
tagData: function (next) {
|
||||
Topics.getTagData(tags, next);
|
||||
},
|
||||
counts: function (next) {
|
||||
db.sortedSetScores('tags:topic:count', uniqueTopicTags, next);
|
||||
}
|
||||
}, function (err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
var tags = uniqueTopicTags.map(function (tag) {
|
||||
return {value: tag};
|
||||
});
|
||||
|
||||
async.parallel({
|
||||
tagData: function (next) {
|
||||
Topics.getTagData(tags, next);
|
||||
},
|
||||
counts: function (next) {
|
||||
db.sortedSetScores('tags:topic:count', uniqueTopicTags, next);
|
||||
}
|
||||
}, next);
|
||||
},
|
||||
function (results, next) {
|
||||
results.tagData.forEach(function (tag, index) {
|
||||
tag.score = results.counts[index] ? results.counts[index] : 0;
|
||||
});
|
||||
@@ -214,9 +214,9 @@ module.exports = function (Topics) {
|
||||
}
|
||||
});
|
||||
|
||||
callback(null, topicTags);
|
||||
});
|
||||
});
|
||||
next(null, topicTags);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
Topics.updateTags = function (tid, tags, callback) {
|
||||
@@ -235,60 +235,54 @@ module.exports = function (Topics) {
|
||||
};
|
||||
|
||||
Topics.deleteTopicTags = function (tid, callback) {
|
||||
Topics.getTopicTags(tid, function (err, tags) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
Topics.getTopicTags(tid, next);
|
||||
},
|
||||
function (tags, next) {
|
||||
async.series([
|
||||
function (next) {
|
||||
db.delete('topic:' + tid + ':tags', next);
|
||||
},
|
||||
function (next) {
|
||||
var sets = tags.map(function (tag) {
|
||||
return 'tag:' + tag + ':topics';
|
||||
});
|
||||
|
||||
db.sortedSetsRemove(sets, tid, next);
|
||||
},
|
||||
function (next) {
|
||||
async.each(tags, function (tag, next) {
|
||||
updateTagCount(tag, next);
|
||||
}, next);
|
||||
}
|
||||
], next);
|
||||
}
|
||||
|
||||
async.series([
|
||||
function (next) {
|
||||
db.delete('topic:' + tid + ':tags', next);
|
||||
},
|
||||
function (next) {
|
||||
var sets = tags.map(function (tag) {
|
||||
return 'tag:' + tag + ':topics';
|
||||
});
|
||||
|
||||
db.sortedSetsRemove(sets, tid, next);
|
||||
},
|
||||
function (next) {
|
||||
async.each(tags, function (tag, next) {
|
||||
updateTagCount(tag, next);
|
||||
}, next);
|
||||
}
|
||||
], function (err) {
|
||||
callback(err);
|
||||
});
|
||||
], function (err) {
|
||||
callback(err);
|
||||
});
|
||||
};
|
||||
|
||||
Topics.searchTags = function (data, callback) {
|
||||
function done(matches) {
|
||||
plugins.fireHook('filter:tags.search', {data: data, matches: matches}, function (err, data) {
|
||||
callback(err, data ? data.matches : []);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (!data || !data.query) {
|
||||
return callback(null, []);
|
||||
}
|
||||
|
||||
if (plugins.hasListeners('filter:topics.searchTags')) {
|
||||
return plugins.fireHook('filter:topics.searchTags', {data: data}, function (err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
if (plugins.hasListeners('filter:topics.searchTags')) {
|
||||
plugins.fireHook('filter:topics.searchTags', {data: data}, next);
|
||||
} else {
|
||||
findMatches(data.query, next);
|
||||
}
|
||||
done(data.matches);
|
||||
});
|
||||
}
|
||||
|
||||
findMatches(data.query, function (err, matches) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
},
|
||||
function (result, next) {
|
||||
plugins.fireHook('filter:tags.search', {data: data, matches: result.matches}, next);
|
||||
},
|
||||
function (result, next) {
|
||||
next(null, result.matches);
|
||||
}
|
||||
done(matches);
|
||||
});
|
||||
], callback);
|
||||
};
|
||||
|
||||
Topics.autocompleteTags = function (data, callback) {
|
||||
@@ -296,41 +290,44 @@ module.exports = function (Topics) {
|
||||
return callback(null, []);
|
||||
}
|
||||
|
||||
if (plugins.hasListeners('filter:topics.autocompleteTags')) {
|
||||
return plugins.fireHook('filter:topics.autocompleteTags', {data: data}, function (err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
if (plugins.hasListeners('filter:topics.autocompleteTags')) {
|
||||
plugins.fireHook('filter:topics.autocompleteTags', {data: data}, next);
|
||||
} else {
|
||||
findMatches(data.query, next);
|
||||
}
|
||||
callback(null, data.matches);
|
||||
});
|
||||
}
|
||||
|
||||
findMatches(data.query, callback);
|
||||
},
|
||||
function (result, next) {
|
||||
next(null, result.matches);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
function findMatches(query, callback) {
|
||||
db.getSortedSetRevRange('tags:topic:count', 0, -1, function (err, tags) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getSortedSetRevRange('tags:topic:count', 0, -1, next);
|
||||
},
|
||||
function (tags, next) {
|
||||
query = query.toLowerCase();
|
||||
|
||||
query = query.toLowerCase();
|
||||
|
||||
var matches = [];
|
||||
for(var i = 0; i < tags.length; ++i) {
|
||||
if (tags[i].toLowerCase().startsWith(query)) {
|
||||
matches.push(tags[i]);
|
||||
if (matches.length > 19) {
|
||||
break;
|
||||
var matches = [];
|
||||
for(var i = 0; i < tags.length; ++i) {
|
||||
if (tags[i].toLowerCase().startsWith(query)) {
|
||||
matches.push(tags[i]);
|
||||
if (matches.length > 19) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matches = matches.sort(function (a, b) {
|
||||
return a > b;
|
||||
});
|
||||
callback(null, matches);
|
||||
});
|
||||
matches = matches.sort(function (a, b) {
|
||||
return a > b;
|
||||
});
|
||||
next(null, {matches: matches});
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
|
||||
Topics.searchAndLoadTags = function (data, callback) {
|
||||
@@ -340,28 +337,28 @@ module.exports = function (Topics) {
|
||||
pageCount: 1
|
||||
};
|
||||
|
||||
if (!data.query || !data.query.length) {
|
||||
if (!data || !data.query || !data.query.length) {
|
||||
return callback(null, searchResult);
|
||||
}
|
||||
Topics.searchTags(data, function (err, tags) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
async.parallel({
|
||||
counts: function (next) {
|
||||
db.sortedSetScores('tags:topic:count', tags, next);
|
||||
},
|
||||
tagData: function (next) {
|
||||
tags = tags.map(function (tag) {
|
||||
return {value: tag};
|
||||
});
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
Topics.searchTags(data, next);
|
||||
},
|
||||
function (tags, next) {
|
||||
async.parallel({
|
||||
counts: function (next) {
|
||||
db.sortedSetScores('tags:topic:count', tags, next);
|
||||
},
|
||||
tagData: function (next) {
|
||||
tags = tags.map(function (tag) {
|
||||
return {value: tag};
|
||||
});
|
||||
|
||||
Topics.getTagData(tags, next);
|
||||
}
|
||||
}, function (err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
Topics.getTagData(tags, next);
|
||||
}
|
||||
}, next);
|
||||
},
|
||||
function (results, next) {
|
||||
results.tagData.forEach(function (tag, index) {
|
||||
tag.score = results.counts[index];
|
||||
});
|
||||
@@ -371,9 +368,9 @@ module.exports = function (Topics) {
|
||||
searchResult.tags = results.tagData;
|
||||
searchResult.matchCount = results.tagData.length;
|
||||
searchResult.pageCount = 1;
|
||||
callback(null, searchResult);
|
||||
});
|
||||
});
|
||||
next(null, searchResult);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
Topics.getRelatedTopics = function (topicData, uid, callback) {
|
||||
|
||||
@@ -872,10 +872,101 @@ describe('Topic\'s', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('tags', function () {
|
||||
var socketTopics = require('../src/socket.io/topics');
|
||||
before(function (done) {
|
||||
async.parallel({
|
||||
topic1: function (next) {
|
||||
topics.post({uid: adminUid, tags: ['php', 'nosql', 'psql', 'nodebb'], title: 'topic title 1', content: 'topic 1 content', cid: topic.categoryId}, next);
|
||||
},
|
||||
topic2: function (next) {
|
||||
topics.post({uid: adminUid, tags: ['javascript', 'mysql', 'python', 'nodejs'], title: 'topic title 2', content: 'topic 2 content', cid: topic.categoryId}, next);
|
||||
}
|
||||
}, function (err, results) {
|
||||
assert.ifError(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return empty array if query is falsy', function (done) {
|
||||
socketTopics.autocompleteTags({uid: adminUid}, {query: ''}, function (err, data) {
|
||||
assert.ifError(err);
|
||||
assert.deepEqual([], data);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should autocomplete tags', function (done) {
|
||||
socketTopics.autocompleteTags({uid: adminUid}, {query: 'p'}, function (err, data) {
|
||||
assert.ifError(err);
|
||||
['php', 'psql', 'python'].forEach(function (tag) {
|
||||
assert.notEqual(data.indexOf(tag), -1);
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return empty array if query is falsy', function (done) {
|
||||
socketTopics.searchTags({uid: adminUid}, {query: ''}, function (err, data) {
|
||||
assert.ifError(err);
|
||||
assert.deepEqual([], data);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should search tags', function (done) {
|
||||
socketTopics.searchTags({uid: adminUid}, {query: 'no'}, function (err, data) {
|
||||
assert.ifError(err);
|
||||
['nodebb', 'nodejs', 'nosql'].forEach(function (tag) {
|
||||
assert.notEqual(data.indexOf(tag), -1);
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return empty array if query is falsy', function (done) {
|
||||
socketTopics.searchAndLoadTags({uid: adminUid}, {query: ''}, function (err, data) {
|
||||
assert.ifError(err);
|
||||
assert.equal(data.matchCount, 0);
|
||||
assert.equal(data.pageCount, 1);
|
||||
assert.deepEqual(data.tags, []);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should search and load tags', function (done) {
|
||||
socketTopics.searchAndLoadTags({uid: adminUid}, {query: 'no'}, function (err, data) {
|
||||
assert.ifError(err);
|
||||
assert.equal(data.matchCount, 3);
|
||||
assert.equal(data.pageCount, 1);
|
||||
var tagData = [
|
||||
{ value: 'nodebb', color: '', bgColor: '', score: 3 },
|
||||
{ value: 'nodejs', color: '', bgColor: '', score: 1 },
|
||||
{ value: 'nosql', color: '', bgColor: '', score: 1 }
|
||||
];
|
||||
assert.deepEqual(data.tags, tagData);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('shold return error if data is invalid', function (done) {
|
||||
socketTopics.loadMoreTags({uid: adminUid}, {after: 'asd'}, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should load more tags', function (done) {
|
||||
socketTopics.loadMoreTags({uid: adminUid}, {after: 0}, function (err, data) {
|
||||
assert.ifError(err);
|
||||
assert(Array.isArray(data.tags));
|
||||
assert.equal(data.nextStart, 100);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user