diff --git a/app/assets/javascripts/discourse/lib/autocomplete.js.es6 b/app/assets/javascripts/discourse/lib/autocomplete.js.es6 index f1b24853ab1..5aa01e495b1 100644 --- a/app/assets/javascripts/discourse/lib/autocomplete.js.es6 +++ b/app/assets/javascripts/discourse/lib/autocomplete.js.es6 @@ -359,7 +359,7 @@ export default function(options) { return true; } } - prevIsGood = /[a-zA-Z\.]/.test(prev); + prevIsGood = /[a-zA-Z\.-]/.test(prev); } } diff --git a/app/assets/javascripts/discourse/models/category.js.es6 b/app/assets/javascripts/discourse/models/category.js.es6 index 6d7a983214f..1a8261dd178 100644 --- a/app/assets/javascripts/discourse/models/category.js.es6 +++ b/app/assets/javascripts/discourse/models/category.js.es6 @@ -298,11 +298,18 @@ Category.reopenClass({ } const emptyTerm = (term === ""); + let slugTerm = term; + + if (!emptyTerm) { + term = term.toLowerCase(); + slugTerm = term; + term = term.replace(/-/g, " "); + } + const categories = Category.listByActivity(); const length = categories.length; var i; var data = []; - term = term.toLowerCase(); const done = () => { return data.length === limit; @@ -311,7 +318,10 @@ Category.reopenClass({ for (i = 0; i < length && !done(); i++) { const category = categories[i]; if ((emptyTerm && !category.get('parent_category_id')) || - (!emptyTerm && category.get('name').toLowerCase().indexOf(term) === 0)) { + (!emptyTerm && + (category.get('name').toLowerCase().indexOf(term) === 0 || + category.get('slug').toLowerCase().indexOf(slugTerm) === 0))) { + data.push(category); } } @@ -320,7 +330,10 @@ Category.reopenClass({ for (i = 0; i < length && !done(); i++) { const category = categories[i]; - if ((!emptyTerm && category.get('name').toLowerCase().indexOf(term) > 0)) { + if (!emptyTerm && + (category.get('name').toLowerCase().indexOf(term) > 0 || + category.get('slug').toLowerCase().indexOf(slugTerm) > 0)) { + if (data.indexOf(category) === -1) data.push(category); } } diff --git a/test/javascripts/models/category-test.js.es6 b/test/javascripts/models/category-test.js.es6 index 157e319189f..cb6c9858e2c 100644 --- a/test/javascripts/models/category-test.js.es6 +++ b/test/javascripts/models/category-test.js.es6 @@ -126,26 +126,22 @@ test('postCountStats', function() { equal(result.length, 0, "should show nothing"); }); -test('search', () => { - const result = (term, opts) => { - return Category.search(term, opts).map((category) => category.get('id')); - }; - +test('search with category name', () => { const store = createStore(), - category1 = store.createRecord('category', { id: 1, name: 'middle term' }), - category2 = store.createRecord('category', { id: 2, name: 'middle term' }); + category1 = store.createRecord('category', { id: 1, name: 'middle term', slug: 'different-slug' }), + category2 = store.createRecord('category', { id: 2, name: 'middle term', slug: 'another-different-slug' }); sandbox.stub(Category, "listByActivity").returns([category1, category2]); - deepEqual(result('term', { limit: 0 }), [], "returns an empty array when limit is 0"); - deepEqual(result(''), [category1.get('id'), category2.get('id')], "orders by activity if no term is matched"); - deepEqual(result('term'), [category1.get('id'), category2.get('id')], "orders by activity"); + deepEqual(Category.search('term', { limit: 0 }), [], "returns an empty array when limit is 0"); + deepEqual(Category.search(''), [category1, category2], "orders by activity if no term is matched"); + deepEqual(Category.search('term'), [category1, category2], "orders by activity"); category2.set('name', 'TeRm start'); - deepEqual(result('tErM'), [category2.get('id'), category1.get('id')], "ignores case of category name and search term"); + deepEqual(Category.search('tErM'), [category2, category1], "ignores case of category name and search term"); category2.set('name', 'term start'); - deepEqual(result('term'), [category2.get('id'), category1.get('id')], "orders matching begin with and then contains"); + deepEqual(Category.search('term'), [category2, category1], "orders matching begin with and then contains"); sandbox.restore(); @@ -154,21 +150,35 @@ test('search', () => { sandbox.stub(Category, "listByActivity").returns([read_restricted_category, category1, child_category1, category2]); - deepEqual(result(''), - [category1.get('id'), category2.get('id'), read_restricted_category.get('id')], + deepEqual(Category.search(''), + [category1, category2, read_restricted_category], "prioritize non read_restricted and does not include child categories when term is blank"); - deepEqual(result('', { limit: 3 }), - [category1.get('id'), category2.get('id'), read_restricted_category.get('id')], + deepEqual(Category.search('', { limit: 3 }), + [category1, category2, read_restricted_category], "prioritize non read_restricted and does not include child categories categories when term is blank with limit"); - deepEqual(result('term'), - [child_category1.get('id'), category2.get('id'), category1.get('id'), read_restricted_category.get('id')], + deepEqual(Category.search('term'), + [child_category1, category2, category1, read_restricted_category], "prioritize non read_restricted"); - deepEqual(result('term', { limit: 3 }), - [child_category1.get('id'), category2.get('id'), read_restricted_category.get('id')], + deepEqual(Category.search('term', { limit: 3 }), + [child_category1, category2, read_restricted_category], "prioritize non read_restricted with limit"); sandbox.restore(); }); + +test('search with category slug', () => { + const store = createStore(), + category1 = store.createRecord('category', { id: 1, name: 'middle term', slug: 'different-slug' }), + category2 = store.createRecord('category', { id: 2, name: 'middle term', slug: 'another-different-slug' }); + + sandbox.stub(Category, "listByActivity").returns([category1, category2]); + + deepEqual(Category.search('different-slug'), [category1, category2], "returns the right categories"); + deepEqual(Category.search('another-different'), [category2], "returns the right categories"); + + category2.set('slug', 'ANOTher-DIFfereNT'); + deepEqual(Category.search('anOtHer-dIfFeREnt'), [category2], "ignores case of category slug and search term"); +});