<commit_before>add_dependencies({
    util: 'js/util.js',
    stream_data: 'js/stream_data.js'
});

set_global('page_params', {
    email: '<EMAIL>',
    domain: 'zulip.com'
});

set_global('feature_flags', {});

var Filter = require('js/filter.js');
var _ = global._;

function assert_same_operators(result, terms) {
    terms = _.map(result, function (term) {
        // If negated flag is undefined, we explicitly
        // set it to false.
        var negated = term.negated;
        if (!negated) {
            negated = false;
        }
        return {
            negated: negated,
            operator: term.operator,
            operand: term.operand
        };
    });
    assert.deepEqual(result, terms);
}

(function test_basics() {
    var operators = [
        {operator: 'stream', operand: 'foo'},
        {operator: 'stream', operand: 'exclude_stream', negated: true},
        {operator: 'topic', operand: 'bar'}
    ];
    var filter = new Filter(operators);

    assert_same_operators(filter.operators(), operators);
    assert.deepEqual(filter.operands('stream'), ['foo']);

    assert(filter.has_operator('stream'));
    assert(!filter.has_operator('search'));

    assert(filter.has_operand('stream', 'foo'));
    assert(!filter.has_operand('stream', 'exclude_stream'));
    assert(!filter.has_operand('stream', 'nada'));

    assert(!filter.is_search());
    assert(filter.can_apply_locally());

    operators = [
        {operator: 'stream', operand: 'foo'},
        {operator: 'topic', operand: 'bar'},
        {operator: 'search', operand: 'pizza'}
    ];
    filter = new Filter(operators);

    assert(filter.is_search());
    assert(! filter.can_apply_locally());

    // If our only stream operator is negated, then for all intents and purposes,
    // we don't consider ourselves to have a stream operator, because we don't
    // want to have the stream in the tab bar or unsubscribe messaging, etc.
    operators = [
        {operator: 'stream', operand: 'exclude', negated: true}
    ];
    filter = new Filter(operators);
    assert(!filter.has_operator('stream'));

    // Negated searches are just like positive searches for our purposes, since
    // the search logic happens on the back end and we need to have can_apply_locally()
    // be false, and we want "Search results" in the tab bar.
    operators = [
        {operator: 'search', operand: 'stop_word', negated: true}
    ];
    filter = new Filter(operators);
    assert(filter.has_operator('search'));
    assert(! filter.can_apply_locally());
}());

(function test_new_style_operators() {
    var term = {
        operator: 'stream',
        operand: 'foo'
    };
    var operators = [term];
    var filter = new Filter(operators);

    assert.deepEqual(filter.operands('stream'), ['foo']);
}());

(function test_public_operators() {
    var operators = [
        {operator: 'stream', operand: 'foo'},
        {operator: 'topic', operand: 'bar'}
    ];

    var filter = new Filter(operators);
    assert_same_operators(filter.public_operators(), operators);

    operators = [
        {operator: 'in', operand: 'all'}
    ];
    filter = new Filter(operators);
    assert_same_operators(filter.public_operators(), []);
}());

(function test_canonicalizations() {
    assert.equal(Filter.canonicalize_operator('Is'), 'is');
    assert.equal(Filter.canonicalize_operator('Stream'), 'stream');
    assert.equal(Filter.canonicalize_operator('Subject'), 'topic');

    var term;
    term = Filter.canonicalize_term({operator: 'Stream', operand: 'Denmark'});
    assert.equal(term.operator, 'stream');
    assert.equal(term.operand, 'Denmark');

    term = Filter.canonicalize_term({operator: 'sender', operand: 'me'});
    assert.equal(term.operator, 'sender');
    assert.equal(term.operand, '<EMAIL>');

    term = Filter.canonicalize_term({operator: 'pm-with', operand: 'me'});
    assert.equal(term.operator, 'pm-with');
    assert.equal(term.operand, '<EMAIL>');

    term = Filter.canonicalize_term({operator: 'search', operand: 'foo'});
    assert.equal(term.operator, 'search');
    assert.equal(term.operand, 'foo');

    term = Filter.canonicalize_term({operator: 'search', operand: 'fOO'});
    assert.equal(term.operator, 'search');
    assert.equal(term.operand, 'foo');

    term = Filter.canonicalize_term({operator: 'search', operand: 123});
    assert.equal(term.operator, 'search');
    assert.equal(term.operand, '123');

    term = Filter.canonicalize_term({operator: 'search', operand: 'abc “xyz”'});
    assert.equal(term.operator, 'search');
    assert.equal(term.operand, 'abc "xyz"');
}());

function get_predicate(operators) {
    operators = _.map(operators, function (op) {
        return {operator: op[0], operand: op[1]};
    });
    return new Filter(operators).predicate();
}

(function test_predicate_basics() {
    // Predicates are functions that accept a message object with the message
    // attributes (not content), and return true if the message belongs in a
    // given narrow. If the narrow parameters include a search, the predicate
    // passes through all messages.
    //
    // To keep these tests simple, we only pass objects with a few relevant attributes
    // rather than full-fledged message objects.
    var predicate = get_predicate([['stream', 'Foo'], ['topic', 'Bar']]);
    assert(predicate({type: 'stream', stream: 'foo', subject: 'bar'}));
    assert(!predicate({type: 'stream', stream: 'foo', subject: 'whatever'}));
    assert(!predicate({type: 'stream', stream: 'wrong'}));
    assert(!predicate({type: 'private'}));

    predicate = get_predicate([['search', 'emoji']]);
    assert(predicate({}));

    predicate = get_predicate([['topic', 'Bar']]);
    assert(!predicate({type: 'private'}));

    predicate = get_predicate([['is', 'private']]);
    assert(predicate({type: 'private'}));
    assert(!predicate({type: 'stream'}));

    predicate = get_predicate([['is', 'starred']]);
    assert(predicate({starred: true}));
    assert(!predicate({starred: false}));

    predicate = get_predicate([['is', 'alerted']]);
    assert(predicate({alerted: true}));
    assert(!predicate({alerted: false}));
    assert(!predicate({}));

    predicate = get_predicate([['is', 'mentioned']]);
    assert(predicate({mentioned: true}));
    assert(!predicate({mentioned: false}));

    predicate = get_predicate([['in', 'all']]);
    assert(predicate({}));

    predicate = get_predicate([['in', 'home']]);
    assert(!predicate({stream: 'unsub'}));
    assert(predicate({type: 'private'}));

    predicate = get_predicate([['near', 5]]);
    assert(predicate({}));

    predicate = get_predicate([['id', 5]]);
    assert(predicate({id: 5}));
    assert(!predicate({id: 6}));

    predicate = get_predicate([['id', 5], ['topic', 'lunch']]);
    assert(predicate({type: 'stream', id: 5, subject: 'lunch'}));
    assert(!predicate({type: 'stream', id: 5, subject: 'dinner'}));

    predicate = get_predicate([['sender', '<EMAIL>']]);
    assert(predicate({sender_email: '<EMAIL>'}));
    assert(!predicate({sender_email: '<EMAIL>'}));<commit_msg>Add test for in-home search when in our special narrow mode.<commit_after>add_dependencies({
    util: 'js/util.js',
    stream_data: 'js/stream_data.js'
});

set_global('page_params', {
    email: '<EMAIL>',
    domain: 'zulip.com'
});

set_global('feature_flags', {});

var Filter = require('js/filter.js');
var _ = global._;

function assert_same_operators(result, terms) {
    terms = _.map(result, function (term) {
        // If negated flag is undefined, we explicitly
        // set it to false.
        var negated = term.negated;
        if (!negated) {
            negated = false;
        }
        return {
            negated: negated,
            operator: term.operator,
            operand: term.operand
        };
    });
    assert.deepEqual(result, terms);
}

(function test_basics() {
    var operators = [
        {operator: 'stream', operand: 'foo'},
        {operator: 'stream', operand: 'exclude_stream', negated: true},
        {operator: 'topic', operand: 'bar'}
    ];
    var filter = new Filter(operators);

    assert_same_operators(filter.operators(), operators);
    assert.deepEqual(filter.operands('stream'), ['foo']);

    assert(filter.has_operator('stream'));
    assert(!filter.has_operator('search'));

    assert(filter.has_operand('stream', 'foo'));
    assert(!filter.has_operand('stream', 'exclude_stream'));
    assert(!filter.has_operand('stream', 'nada'));

    assert(!filter.is_search());
    assert(filter.can_apply_locally());

    operators = [
        {operator: 'stream', operand: 'foo'},
        {operator: 'topic', operand: 'bar'},
        {operator: 'search', operand: 'pizza'}
    ];
    filter = new Filter(operators);

    assert(filter.is_search());
    assert(! filter.can_apply_locally());

    // If our only stream operator is negated, then for all intents and purposes,
    // we don't consider ourselves to have a stream operator, because we don't
    // want to have the stream in the tab bar or unsubscribe messaging, etc.
    operators = [
        {operator: 'stream', operand: 'exclude', negated: true}
    ];
    filter = new Filter(operators);
    assert(!filter.has_operator('stream'));

    // Negated searches are just like positive searches for our purposes, since
    // the search logic happens on the back end and we need to have can_apply_locally()
    // be false, and we want "Search results" in the tab bar.
    operators = [
        {operator: 'search', operand: 'stop_word', negated: true}
    ];
    filter = new Filter(operators);
    assert(filter.has_operator('search'));
    assert(! filter.can_apply_locally());
}());

(function test_new_style_operators() {
    var term = {
        operator: 'stream',
        operand: 'foo'
    };
    var operators = [term];
    var filter = new Filter(operators);

    assert.deepEqual(filter.operands('stream'), ['foo']);
}());

(function test_public_operators() {
    var operators = [
        {operator: 'stream', operand: 'foo'},
        {operator: 'topic', operand: 'bar'}
    ];

    var filter = new Filter(operators);
    assert_same_operators(filter.public_operators(), operators);

    operators = [
        {operator: 'in', operand: 'all'}
    ];
    filter = new Filter(operators);
    assert_same_operators(filter.public_operators(), []);
}());

(function test_canonicalizations() {
    assert.equal(Filter.canonicalize_operator('Is'), 'is');
    assert.equal(Filter.canonicalize_operator('Stream'), 'stream');
    assert.equal(Filter.canonicalize_operator('Subject'), 'topic');

    var term;
    term = Filter.canonicalize_term({operator: 'Stream', operand: 'Denmark'});
    assert.equal(term.operator, 'stream');
    assert.equal(term.operand, 'Denmark');

    term = Filter.canonicalize_term({operator: 'sender', operand: 'me'});
    assert.equal(term.operator, 'sender');
    assert.equal(term.operand, '<EMAIL>');

    term = Filter.canonicalize_term({operator: 'pm-with', operand: 'me'});
    assert.equal(term.operator, 'pm-with');
    assert.equal(term.operand, '<EMAIL>');

    term = Filter.canonicalize_term({operator: 'search', operand: 'foo'});
    assert.equal(term.operator, 'search');
    assert.equal(term.operand, 'foo');

    term = Filter.canonicalize_term({operator: 'search', operand: 'fOO'});
    assert.equal(term.operator, 'search');
    assert.equal(term.operand, 'foo');

    term = Filter.canonicalize_term({operator: 'search', operand: 123});
    assert.equal(term.operator, 'search');
    assert.equal(term.operand, '123');

    term = Filter.canonicalize_term({operator: 'search', operand: 'abc “xyz”'});
    assert.equal(term.operator, 'search');
    assert.equal(term.operand, 'abc "xyz"');
}());

function get_predicate(operators) {
    operators = _.map(operators, function (op) {
        return {operator: op[0], operand: op[1]};
    });
    return new Filter(operators).predicate();
}

(function test_predicate_basics() {
    // Predicates are functions that accept a message object with the message
    // attributes (not content), and return true if the message belongs in a
    // given narrow. If the narrow parameters include a search, the predicate
    // passes through all messages.
    //
    // To keep these tests simple, we only pass objects with a few relevant attributes
    // rather than full-fledged message objects.
    var predicate = get_predicate([['stream', 'Foo'], ['topic', 'Bar']]);
    assert(predicate({type: 'stream', stream: 'foo', subject: 'bar'}));
    assert(!predicate({type: 'stream', stream: 'foo', subject: 'whatever'}));
    assert(!predicate({type: 'stream', stream: 'wrong'}));
    assert(!predicate({type: 'private'}));

    predicate = get_predicate([['search', 'emoji']]);
    assert(predicate({}));

    predicate = get_predicate([['topic', 'Bar']]);
    assert(!predicate({type: 'private'}));

    predicate = get_predicate([['is', 'private']]);
    assert(predicate({type: 'private'}));
    assert(!predicate({type: 'stream'}));

    predicate = get_predicate([['is', 'starred']]);
    assert(predicate({starred: true}));
    assert(!predicate({starred: false}));

    predicate = get_predicate([['is', 'alerted']]);
    assert(predicate({alerted: true}));
    assert(!predicate({alerted: false}));
    assert(!predicate({}));

    predicate = get_predicate([['is', 'mentioned']]);
    assert(predicate({mentioned: true}));
    assert(!predicate({mentioned: false}));

    predicate = get_predicate([['in', 'all']]);
    assert(predicate({}));

    predicate = get_predicate([['in', 'home']]);
    assert(!predicate({stream: 'unsub'}));
    assert(predicate({type: 'private'}));
    global.page_params.narrow_stream = 'kiosk';
    assert(predicate({stream: 'kiosk'}));

    predicate = get_predicate([['near', 5]]);
    assert(predicate({}));

    predicate = get_predicate([['id', 5]]);
    assert(predicate({id: 5}));
    assert(!predicate({id: 6}));

    predicate = get_predicate([['id', 5], ['topic', 'lunch']]);
    assert(predicate({type: 'stream', id: 5, subject: 'lunch'}));
    assert(!predicate({type: 'stream', id: 5, subject: 'dinner'}));

    predicate = get_predicate([['sender', '<EMAIL>']]);
    assert(predicate({sender_email: '<EMAIL>'}));
    assert(!predicate({sender_email: '<EMAIL>'}));
{'fraction_non_alphanumeric': 0.1768194822412951, 'fraction_numerical': 0.0020933640360058614, 'mean_word_length': 3.832097100472016, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3613216', 'n_tokens_mistral': 4468, 'n_tokens_neox': 4398, 'n_words': 1019}