From 7d47f4b067ac893267341d58d214a85b07cb4bec Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 5 Dec 2016 15:09:13 +0300 Subject: [PATCH] tag tests --- src/socket.io/topics/tags.js | 19 ++- src/topics/tags.js | 235 +++++++++++++++++------------------ test/topics.js | 91 ++++++++++++++ 3 files changed, 216 insertions(+), 129 deletions(-) diff --git a/src/socket.io/topics/tags.js b/src/socket.io/topics/tags.js index ab0a0221ea..67e48fcce8 100644 --- a/src/socket.io/topics/tags.js +++ b/src/socket.io/topics/tags.js @@ -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); }; }; diff --git a/src/topics/tags.js b/src/topics/tags.js index ee8892b1cf..a88c5119d5 100644 --- a/src/topics/tags.js +++ b/src/topics/tags.js @@ -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); - } - - 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; + async.waterfall([ + function (next) { + db.getSortedSetRevRange('tags:topic:count', 0, -1, next); + }, + function (tags, next) { + 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; + } } } - } - 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}; - }); - - Topics.getTagData(tags, next); - } - }, function (err, results) { - if (err) { - return callback(err); - } + 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); + } + }, 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) { diff --git a/test/topics.js b/test/topics.js index 392296928a..4b85261ef9 100644 --- a/test/topics.js +++ b/test/topics.js @@ -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(); + }); + }); });