<commit_before>(function (root, factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
        define(['escallmatch', 'esprima', 'estraverse', 'espurify', 'assert'], factory);
    } else if (typeof exports === 'object') {
        factory(require('..'), require('esprima'), require('estraverse'), require('espurify'), require('assert'));
    } else {
        factory(root.escallmatch, root.esprima, root.estraverse, root.espurify, root.assert);
    }
}(this, function (
    escallmatch,
    esprima,
    estraverse,
    espurify,
    assert
) {


    function matchCode (matcher, targetCode) {
        var esprimaOptions = {tolerant: true, loc: true, tokens: true, raw: true};
        var ast = esprima.parse(targetCode, esprimaOptions);
        var calls = [];
        var args = [];
        var captured = {};
        estraverse.traverse(ast, {
            leave: function (currentNode, parentNode) {
                if (matcher.test(currentNode)) {
                    calls.push(currentNode);
                }
                var matched = matcher.matchArgument(currentNode, parentNode);
                if (matched) {
                    args.push(matched);
                    captured[matched.name] = currentNode;
                }
            }
        });
        return {
            calls: calls,
            args: args,
            captured: captured
        };
    }


    describe('API definition validation', function () {
        it('syntax error', function () {
            assert.throws(function () {
                escallmatch('assert(actual, ');
            }, Error);
        });
        it('argument name should be unique', function () {
            assert.throws(function () {
                escallmatch('assert(actual, actual)');
            }, /Duplicate argument name: actual/);
        });
    });


    describe('optional parameter assert(actual, [message])', function () {
        beforeEach(function () {
            this.matcher = escallmatch('assert(actual, [message])');
        });
        it('with message', function () {
            var matched = matchCode(this.matcher, 'it("test foo", function () { assert(foo, "message"); })');
            assert.equal(matched.calls.length, 1);
            assert.equal(matched.args.length, 2);
            assert.deepEqual(matched.args[0], {name: 'actual', kind: 'mandatory'});
            assert.deepEqual(matched.args[1], {name: 'message', kind: 'optional'});
            assert(matched.captured['actual']);
            assert(matched.captured['message']);
            assert.deepEqual(espurify(matched.captured['actual']), {
                type: 'Identifier',
                name: 'foo'
            });
            assert.deepEqual(espurify(matched.captured['message']), {
                type: 'Literal',
                value: 'message'
            });
        });
        it('without message', function () {
            var matched = matchCode(this.matcher, 'it("test foo", function () { assert(foo); })');
            assert.equal(matched.calls.length, 1);
            assert.equal(matched.args.length, 1);<commit_msg>test(escallmatch): one more test for ensuring arguments are unique<commit_after>(function (root, factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
        define(['escallmatch', 'esprima', 'estraverse', 'espurify', 'assert'], factory);
    } else if (typeof exports === 'object') {
        factory(require('..'), require('esprima'), require('estraverse'), require('espurify'), require('assert'));
    } else {
        factory(root.escallmatch, root.esprima, root.estraverse, root.espurify, root.assert);
    }
}(this, function (
    escallmatch,
    esprima,
    estraverse,
    espurify,
    assert
) {


    function matchCode (matcher, targetCode) {
        var esprimaOptions = {tolerant: true, loc: true, tokens: true, raw: true};
        var ast = esprima.parse(targetCode, esprimaOptions);
        var calls = [];
        var args = [];
        var captured = {};
        estraverse.traverse(ast, {
            leave: function (currentNode, parentNode) {
                if (matcher.test(currentNode)) {
                    calls.push(currentNode);
                }
                var matched = matcher.matchArgument(currentNode, parentNode);
                if (matched) {
                    args.push(matched);
                    captured[matched.name] = currentNode;
                }
            }
        });
        return {
            calls: calls,
            args: args,
            captured: captured
        };
    }


    describe('API definition validation', function () {
        it('syntax error', function () {
            assert.throws(function () {
                escallmatch('assert(actual, ');
            }, Error);
        });
        it('argument name should be unique', function () {
            assert.throws(function () {
                escallmatch('assert(actual, actual)');
            }, /Duplicate argument name: actual/);
            assert.throws(function () {
                escallmatch('assert(actual, [actual])');
            }, /Duplicate argument name: actual/);
        });
    });


    describe('optional parameter assert(actual, [message])', function () {
        beforeEach(function () {
            this.matcher = escallmatch('assert(actual, [message])');
        });
        it('with message', function () {
            var matched = matchCode(this.matcher, 'it("test foo", function () { assert(foo, "message"); })');
            assert.equal(matched.calls.length, 1);
            assert.equal(matched.args.length, 2);
            assert.deepEqual(matched.args[0], {name: 'actual', kind: 'mandatory'});
            assert.deepEqual(matched.args[1], {name: 'message', kind: 'optional'});
            assert(matched.captured['actual']);
            assert(matched.captured['message']);
            assert.deepEqual(espurify(matched.captured['actual']), {
                type: 'Identifier',
                name: 'foo'
            });
            assert.deepEqual(espurify(matched.captured['message']), {
                type: 'Literal',
                value: 'message'
            });
        });
        it('without message', function () {
            var matched = matchCode(this.matcher, 'it("test foo", function () { assert(foo); })');
            assert.equal(matched.calls.length, 1);
            assert.equal(matched.args.length, 1);
{'fraction_non_alphanumeric': 0.1483831038217546, 'fraction_numerical': 0.0018567228841095467, 'mean_word_length': 2.003717472118959, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '6458077', 'n_tokens_mistral': 1754, 'n_tokens_neox': 1712, 'n_words': 354}