示例#1
0
    QUnit.test('Select a product in the list and check for template loading', async function (assert){
        assert.expect(1);

        var product_configurator_form = await createView({
            View: ProductConfiguratorFormView,
            model: 'sale_product_configurator',
            data: this.data,
            arch:
                '<form js_class="product_configurator_form">' +
                    '<group>' +
                        '<field name="product_template_id" class="oe_product_configurator_product_template_id" />' +
                        '<field name="product_template_attribute_value_ids" invisible="1" />' +
                        '<field name="product_no_variant_attribute_value_ids" invisible="1" />' +
                        '<field name="product_custom_attribute_value_ids" invisible="1" />' +
                    '</group>' +
                    '<footer>' +
                        '<button string="Add" class="btn-primary o_sale_product_configurator_add disabled"/>' +
                        '<button string="Cancel" class="btn-secondary" special="cancel"/>' +
                    '</footer>' +
                '</form>',
                mockRPC: function (route) {
                    if (route === '/sale_product_configurator/configure') {
                        assert.ok(true);
                        return Promise.resolve('<div>plop</div>');
                    }
                    return this._super.apply(this, arguments);
                }
        });
        await testUtils.dom.click(product_configurator_form.$('.o_input'));
        await testUtils.dom.click($("ul.ui-autocomplete li a:contains('Customizable Desk')").mouseenter());
        product_configurator_form.destroy();
    });
示例#2
0
                function(assert) {
                    assert.expect(3);

                    var html =
                        "<div>" +
                            '<a name="a1" type="action" class="simple">simple</a>' +
                            '<a name="a2" type="action" class="with-child">' +
                                "<span>child</input>" +
                            "</a>" +
                        "</div>";

                    var view = createView({
                        View: getHtmlView(html, "test"),
                        data: this.data,
                        model: "test_model",
                        arch: "<test/>",
                        intercepts: {
                            do_action: function(event) {
                                assert.step(event.data.action);
                            }
                        }
                    });
                    testUtils.dom.click(view.$(".simple"));
                    testUtils.dom.click(view.$(".with-child span"));
                    assert.verifySteps(["a1", "a2"]);
                }
QUnit.test('Pending', async function (assert) {
    assert.expect(7);

    this.data['mail.message'].records[0].snailmail_status = 'pending';
    this.data['mail.message'].records[0].snailmail_error = false;

    var form = await createView({
        View: FormView,
        model: 'account.invoice',
        res_id: 1,
        data: this.data,
        services: this.services,
        arch: getArch(),
    });

    assert.containsOnce(form, '.o_thread_snailmail_tooltip_container',
        "Snailmail icon should appear on message");
    assert.containsOnce(form, '.o_thread_message_snailmail_pending',
        "Snailmail status of message should be 'pending'");
    assert.containsNone(form, '.o_thread_tooltip_snailmail',
        "No tooltip should be present");

    testUtils.dom.triggerMouseEvent(form.$('.o_thread_message_snailmail_pending'), 'mouseenter');
    assert.ok($('.o_thread_tooltip_snailmail:visible').length,
        "Tooltip should appear when hovering the Snailmail Icon");
    assert.ok($('.o_thread_tooltip_snailmail_icon.fa-clock-o').length,
        "Tooltip should show correct icon");
    assert.ok($('.o_thread_tooltip_snailmail:contains("Awaiting Dispatch")').length,
        "Tooltip should show correct text");

    await testUtils.dom.click(form.$('.o_thread_message_snailmail_pending'));
    assert.containsNone($('.modal'), "No modal should open on click");

    form.destroy();
});
示例#4
0
    QUnit.test('click on an item should toggle item', function (assert) {
        assert.expect(9);

        var eventNumber = 0;

        var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items, {
            intercepts: {
                menu_item_toggled: function (ev) {
                    eventNumber++;
                    assert.strictEqual(ev.data.itemId, 1);
                    if (eventNumber === 1) {
                        assert.strictEqual(ev.data.isActive, true);
                    } else {
                        assert.strictEqual(ev.data.isActive, false);
                    }
                },
            },
        });
        testUtils.dom.click(dropdownMenu.$('button:first'));
        assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:first > .dropdown-item'), 'selected');
        testUtils.dom.click(dropdownMenu.$('.o_menu_item a').first());
        assert.hasClass(dropdownMenu.$('.o_menu_item:first > .dropdown-item'), 'selected');
        assert.ok(dropdownMenu.$('.o_menu_item:first').is(':visible'),
            'item should still be visible');
        testUtils.dom.click(dropdownMenu.$('.o_menu_item a').first());
        assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:first > .dropdown-item'), 'selected');
        assert.ok(dropdownMenu.$('.o_menu_item:first').is(':visible'),
            'item should still be visible');

        dropdownMenu.destroy();
    });
示例#5
0
        QUnit.test('Select a product in the list and check for template loading', function (assert){
            assert.expect(1);

            var product_configurator_form = createView({
                View: ProductConfiguratorFormView,
                model: 'sale_product_configurator',
                data: this.data,
                arch:
                    '<form js_class="product_configurator_form">' +
                        '<group>' +
                            '<field name="product_template_id" class="oe_product_configurator_product_template_id" />' +
                        '</group>' +
                        '<footer>' +
                            '<button string="Add" class="btn-primary o_sale_product_configurator_add disabled"/>' +
                            '<button string="Cancel" class="btn-secondary" special="cancel"/>' +
                        '</footer>' +
                    '</form>',
                    mockRPC: function (route) {
                        if (route === '/product_configurator/configure') {
                            assert.ok(true);
                            return $.Deferred().then(_.constant(1));
                        }
                        return this._super.apply(this, arguments);
                    }
            });
            testUtils.dom.click(product_configurator_form.$('.o_input'));
            testUtils.dom.click($("ul.ui-autocomplete li a:contains('Customizable Desk')").mouseenter());
        });
    QUnit.test('select a groupBy of no date type in Add Custom Group menu add properly that groupBy to menu', function (assert) {
        assert.expect(6);

        var groupByMenu = createGroupByMenu(
            [],
            {
                fieldName: {sortable: true, name: 'candlelight', string: 'Candlelight', type: 'boolean'},
            },
            {
                intercepts: {
                    new_groupBy: function (ev) {
                        assert.strictEqual(ev.data.description, 'Candlelight');
                        assert.strictEqual(ev.data.fieldName, 'fieldName');
                        assert.strictEqual(ev.data.fieldType, 'boolean');
                        assert.strictEqual(ev.data.type, 'groupBy');
                        groupByMenu.update([{
                            description: 'Candlelight',
                            groupNumber: 1,
                            isActive: true,
                        }]);
                    },
                },
            }
        );
        testUtils.dom.click(groupByMenu.$('button:first'));
        testUtils.dom.click(groupByMenu.$('.o_add_custom_group'));
        assert.strictEqual(groupByMenu.$('select').val(), 'fieldName',
            'the select value should be "fieldName"');
        testUtils.dom.click(groupByMenu.$('button.o_apply_group'));
        assert.containsOnce(groupByMenu, '.o_menu_item > .dropdown-item.selected', 'there should be a groupby selected');
        groupByMenu.destroy();
    });
示例#7
0
    QUnit.test('delegate', async function (assert) {
        assert.expect(5);

        var a = [];
        var widget = new (Widget.extend({
            template: 'test.widget.template',
            events: {
                'click': function () {
                    a[0] = true;
                    assert.strictEqual(this, widget, "should trigger events in widget");
                },
                'click li.class-3': 'class3',
                'change input': function () { a[2] = true; }
            },
            class3: function () { a[1] = true; }
        }))();
        widget.renderElement();

        await testUtils.dom.click(widget.$el, {allowInvisible: true});
        await testUtils.dom.click(widget.$('li:eq(3)'), {allowInvisible: true});
        await testUtils.fields.editAndTrigger(widget.$('input:last'), 'foo', 'change');

        for(var i=0; i<3; ++i) {
            assert.ok(a[i], "should pass test " + i);
        }
        widget.destroy();
    });
示例#8
0
    QUnit.test('undelegate', async function (assert) {
        assert.expect(4);

        var clicked = false;
        var newclicked = false;

        var widget = new (Widget.extend({
            template: 'test.widget.template',
            events: { 'click li': function () { clicked = true; } }
        }))();

        widget.renderElement();
        widget.$el.on('click', 'li', function () { newclicked = true; });

        await testUtils.dom.clickFirst(widget.$('li'), {allowInvisible: true});
        assert.ok(clicked, "should trigger bound events");
        assert.ok(newclicked, "should trigger bound events");

        clicked = newclicked = false;
        widget._undelegateEvents();
        await testUtils.dom.clickFirst(widget.$('li'), {allowInvisible: true});
        assert.ok(!clicked, "undelegate should unbind events delegated");
        assert.ok(newclicked, "undelegate should only unbind events it created");
        widget.destroy();
    });
示例#9
0
QUnit.test('thread window\'s input can still be focused when the UI is blocked', function (assert) {
    assert.expect(2);

    var parent = this.createParent({
        data: this.data,
        services: this.services,
    });

    var $dom = $('#qunit-fixture');

    // get channel instance to link to thread window
    var channel = parent.call('mail_service', 'getChannel', 1);
    channel.detach();

    var $input = $('<input/>', {type: 'text'}).appendTo($dom);
    testUtils.dom.click($input.focus());
    assert.strictEqual(document.activeElement, $input[0],
        "fake input should be focused");

    framework.blockUI();
    // cannot force focus here otherwise the test
    // makes no sense, this test is just about
    // making sure that the code which forces the
    // focus on click is not removed
    testUtils.dom.click($('.o_thread_window .o_composer_text_field'));
    assert.strictEqual(document.activeElement,
        $('.o_thread_window .o_composer_text_field')[0],
        "thread window's input should now be focused");

    framework.unblockUI();
    parent.destroy();
});
示例#10
0
    QUnit.test("building a domain with a datetime", function (assert) {
        assert.expect(2);

        var $target = $("#qunit-fixture");

        // Create the domain selector and its mock environment
        var domainSelector = new DomainSelector(null, "partner", [["nice_datetime", "=", "2017-03-27 15:42:00"]], {
            readonly: false,
        });
        testUtils.mock.addMockEnvironment(domainSelector, {data: this.data});
        domainSelector.appendTo($target);

        // Check that there is a datepicker to choose the date
        var $datepicker = domainSelector.$(".o_datepicker:visible");
        assert.strictEqual($datepicker.length, 1,
            "there should be a datepicker");

        var val = $datepicker.find('input').val();
        testUtils.dom.openDatepicker($datepicker);
        testUtils.dom.clickFirst($('.bootstrap-datetimepicker-widget :not(.today)[data-action="selectDay"]'));
        assert.notEqual(domainSelector.$(".o_datepicker:visible input").val(), val,
            "datepicker value should have changed");

        domainSelector.destroy();
    });
示例#11
0
    QUnit.test('adding a simple filter works', function (assert) {
        assert.expect(6);

        delete this.fields.date_field;
        var filterMenu = createFilterMenu([], this.fields, {
            intercepts: {
                new_filters: function (ev) {
                    var filter = ev.data.filters[0];
                    assert.strictEqual(filter.type, 'filter');
                    assert.strictEqual(filter.description, 'Boolean Field is true');
                    assert.strictEqual(filter.domain, '[[\"boolean_field\",\"=\",True]]');
                    filterMenu.update([{
                        isActive: true,
                        description: '?',
                        domain: '?',
                        groupNumber: 1,
                    }]);
                },
            },
        });
        // open menu dropdown and custom filter submenu, remove existing prop
        testUtils.dom.click(filterMenu.$('span.fa-filter'));
        testUtils.dom.click(filterMenu.$('.o_add_custom_filter'));
        // click on apply to activate filter
        testUtils.dom.click(filterMenu.$('.o_apply_filter'));
        assert.containsNone(filterMenu, '.o_filter_condition');
        assert.containsN(filterMenu, '.dropdown-divider', 2);
        assert.isNotVisible(filterMenu.$('.dropdown-divider').eq(0));
        filterMenu.destroy();
    });
示例#12
0
    QUnit.test('SelectCreateDialog: save current search', function (assert) {
        assert.expect(4);

        testUtils.mock.patch(ListController, {
            getContext: function () {
                return {
                    shouldBeInFilterContext: true,
                };
            },
        });

        var parent = createParent({
            data: this.data,
            archs: {
                'partner,false,list':
                    '<tree>' +
                        '<field name="display_name"/>' +
                    '</tree>',
                'partner,false,search':
                    '<search>' +
                       '<filter name="bar" help="Bar" domain="[(\'bar\', \'=\', True)]"/>' +
                    '</search>',

            },
            intercepts: {
                create_filter: function (event) {
                    var filter = event.data.filter;
                    assert.deepEqual(filter.domain, "[('bar', '=', True)]",
                        "should save the correct domain");
                    assert.deepEqual(filter.context, {shouldBeInFilterContext: true},
                        "should save the correct context");
                },
            },
        });

        var dialog = new dialogs.SelectCreateDialog(parent, {
            context: {shouldNotBeInFilterContext: false},
            res_model: 'partner',
        }).open();

        assert.containsN(dialog, '.o_data_row', 3,
            "should contain 3 records");

        // filter on bar
        testUtils.dom.click(dialog.$('.o_dropdown_toggler_btn:contains(Filters)'));
        testUtils.dom.click(dialog.$('.o_filters_menu a:contains(Bar)'));

        assert.containsN(dialog, '.o_data_row', 2,
            "should contain 2 records");

        // save filter
        testUtils.dom.click(dialog.$('.o_dropdown_toggler_btn:contains(Favorites)'));
        testUtils.dom.click(dialog.$('.o_save_search'));
        dialog.$('.o_save_name input[type=text]').val('some name'); // name the filter
        testUtils.dom.click(dialog.$('.o_save_name button'));

        testUtils.mock.unpatch(ListController);
        parent.destroy();
    });
示例#13
0
QUnit.test('messaging menu widget: do not open chat window twice on preview clicked', async function (assert) {
    // This test assumes that a condition for opening chat window is to
    // successfully fetch messages beforehand.
    assert.expect(4);

    var self = this;
    // Used to pause `message_fetch` after opening the messaging menu.
    // This is necessary `message_fetch` on mailbox_inbox is required to
    // display the previews.
    var lockMessageFetch = false;
    var messageFetchDef = testUtils.makeTestPromise();

    var messagingMenu = new MessagingMenu();
    testUtils.addMockEnvironment(messagingMenu, {
        services: this.services,
        data: this.data,
        session: { partner_id: 1 },
        mockRPC: function (route, args) {
            if (args.method === 'message_fetch' && lockMessageFetch) {
                var _super = this._super.bind(this);
                return messageFetchDef.then(function () {
                    assert.step('message_fetch');
                    return _super(route, args);
                });
            }
            if (args.method === 'channel_minimize') {
                assert.step('channel_minimize');
                // called to detach thread in chat window
                // simulate longpolling response with new chat window state
                var channelInfo = _.extend({}, self.data['mail.channel'].records[0], {
                    is_minimized: true,
                    state: 'open',
                });
                var notifications = [ [['myDB', 'res.partner'], channelInfo] ];
                messagingMenu.call('bus_service', 'trigger', 'notification', notifications);
            }
            return this._super.apply(this, arguments);
        },
    });
    await messagingMenu.appendTo($('#qunit-fixture'));

    // Opening chat window from messaging menu (pending from `messageFetchDef`)
    await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
    lockMessageFetch = true;
    await testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
    messageFetchDef.resolve();

    await testUtils.nextTick();
    assert.strictEqual($('.o_thread_window').length, 1,
        "should only display a single chat window");
    assert.verifySteps([
        'message_fetch',
        'channel_minimize',
    ], "should have fetched messages only once");

    messagingMenu.destroy();
});
示例#14
0
QUnit.test("messaging menu widget: mark as read on thread preview", async function ( assert ) {
    assert.expect(8);

    testUtils.mock.patch(DocumentThread, {
            markAsRead: function () {
                if (
                    this.getDocumentModel() === 'crm.lead' &&
                    this.getDocumentID() === 126
                ) {
                    assert.step('markedAsRead');
                }
            },
        });

    this.data['mail.message'].records = [{
        id: 10,
        channel_ids: ['mailbox_inbox'],
        res_id: 126,
        needaction: true,
        module_icon: "/crm/static/description/icon.png",
        date: "2018-04-05 06:37:26",
        subject: "Re: Interest in your Graphic Design Project",
        model: "crm.lead",
        body: "<span>Testing Messaging</span>"
    }];

    var messagingMenu = new MessagingMenu();
    testUtils.mock.addMockEnvironment(messagingMenu, {
        services: this.services,
        data: this.data,
    });

    await messagingMenu.appendTo($('#qunit-fixture'));
    await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
    assert.hasClass(messagingMenu.$el,'o_mail_systray_item',
        'should be the instance of widget');
    assert.hasClass(messagingMenu.$el,'show',
        'MessagingMenu should be open');

    var $preview = messagingMenu.$('.o_mail_preview.o_preview_unread');
    assert.strictEqual($preview.length, 1,
        "should have one unread preview");
    assert.strictEqual($preview.data('document-model'), 'crm.lead',
        "should preview be linked to correct document model");
    assert.strictEqual($preview.data('document-id'), 126,
        "should preview be linked to correct document ID");
    assert.containsOnce(messagingMenu, '.o_mail_preview_mark_as_read',
        "should have mark as read icon next to preview");

    await testUtils.dom.click(messagingMenu.$(".o_mail_preview_mark_as_read"));

    assert.verifySteps(['markedAsRead'],
        "the document thread should be marked as read");

    testUtils.mock.unpatch(DocumentThread);
    messagingMenu.destroy();
});
示例#15
0
    QUnit.test('select a groupBy of date type in Add Custom Group menu add properly that groupBy to menu', function (assert) {
        assert.expect(13);

        INTERVAL_OPTIONS = INTERVAL_OPTIONS.map(function (option) {
            return _.extend(option, {description: option.description.toString()});
        });

        var groupByMenu = createGroupByMenu(
            [],
            this.fields,
            {
                intercepts: {
                    new_groupBy: function (ev) {
                        assert.strictEqual(ev.data.description, 'Super Date');
                        assert.strictEqual(ev.data.fieldName, 'fieldName');
                        assert.strictEqual(ev.data.fieldType, 'date');
                        assert.strictEqual(ev.data.type, 'groupBy');
                        assert.strictEqual(ev.data.hasOptions, true);
                        assert.deepEqual(ev.data.options, controlPanelViewParameters.INTERVAL_OPTIONS);
                        assert.strictEqual(ev.data.defaultOptionId, controlPanelViewParameters.DEFAULT_INTERVAL);
                        assert.strictEqual(ev.data.currentOptionId, false);
                        groupByMenu.update([{
                            description: 'Super Date',
                            fieldName: 'fieldName',
                            groupNumber: 1,
                            isActive: true,
                            hasOptions: true,
                            options: controlPanelViewParameters.INTERVAL_OPTIONS,
                            currentOptionId: controlPanelViewParameters.DEFAULT_INTERVAL,
                        }]);
                    },
                },
            }
        );
        // open groupBy menu
        testUtils.dom.click(groupByMenu.$('button:first'));
        // open Add Custom Group submenu
        testUtils.dom.click(groupByMenu.$('.o_add_custom_group'));
        // select fieldName
        assert.strictEqual(groupByMenu.$('select').val(), 'fieldName',
            'the select value should be "fieldName"');
        // create new groupBy of type date
        groupByMenu.$('button.o_apply_group').click();
        assert.strictEqual(groupByMenu.$('.o_menu_item > .dropdown-item.selected').length, 1,
            'there should be a groupby selected');
        assert.strictEqual(groupByMenu.$('.o_menu_item .o_submenu_switcher').length, 1,
            'there should be options available');
        // open options submenu
        groupByMenu.$('.o_menu_item .o_submenu_switcher').click();
        assert.strictEqual(groupByMenu.$('.o_item_option').length, 5,
            'there should be five options available');
        assert.strictEqual(groupByMenu.$('.o_add_custom_group').length, 0,
            'there should be no more a Add Custome Group submenu');

        groupByMenu.destroy();
    });
示例#16
0
        return concurrency.delay(0).then(function () {
            assert.ok(graph.$('text.nv-legend-text:contains(Count)').length,
                "should have used the correct measure");
            assert.ok(graph.$buttons.find('.dropdown-item[data-field="foo"]').length,
                "should have foo in the list of measures");
            testUtils.dom.click(graph.$buttons.find('.dropdown-toggle:contains(Measures)'));
            testUtils.dom.click(graph.$buttons.find('.dropdown-item[data-field="foo"]'));

            return concurrency.delay(0);
        }).then(function () {
示例#17
0
    QUnit.test('settings views does not read existing id when coming back in breadcrumbs', function (assert) {
        assert.expect(8);

        var actions = [{
            id: 1,
            name: 'Settings view',
            res_model: 'project',
            type: 'ir.actions.act_window',
            views: [[1, 'form']],
        }, {
            id: 4,
            name: 'Other action',
            res_model: 'project',
            type: 'ir.actions.act_window',
            views: [[2, 'list']],
        }];
        var archs = {
            'project,1,form': '<form string="Settings" js_class="base_settings">' +
                    '<div class="app_settings_block" string="CRM" data-key="crm">' +
                        '<button name="4" string="Execute action" type="action"/>' +
                    '</div>' +
                '</form>',
            'project,2,list': '<tree><field name="foo"/></tree>',
            'project,false,search': '<search></search>',
        };

        var actionManager = createActionManager({
            actions: actions,
            archs: archs,
            data: this.data,
            mockRPC: function (route, args) {
                if (args.method) {
                    assert.step(args.method);
                }
                return this._super.apply(this, arguments);
            },
        });

        actionManager.doAction(1);
        testUtils.dom.click(actionManager.$('button[name="4"]'));
        testUtils.dom.click($('.o_control_panel .breadcrumb-item a'));
        assert.hasClass(actionManager.$('.o_form_view'), 'o_form_editable');
        assert.verifySteps([
            'load_views', // initial setting action
            'default_get', // this is a setting view => create new record
            'create', // when we click on action button => save
            'read', // with save, we have a reload... (not necessary actually)
            'load_views', // for other action in breadcrumb,
                    // with a searchread (not shown here since it is a route)
            'default_get', // when we come back, we want to restart from scratch
        ]);

        actionManager.destroy();
    });
示例#18
0
QUnit.test('No Price Available', async function (assert) {
    assert.expect(11);

    this.data['mail.message'].records[0].snailmail_status = 'no_price_available';
    this.data['mail.message'].records[0].snailmail_error = true;

    var form = await createView({
        View: FormView,
        model: 'account.invoice',
        res_id: 1,
        data: this.data,
        services: this.services,
        arch: getArch(),
        mockRPC: function (route, args) {
            if (args.method === 'cancel_letter' && args.model === 'mail.message' && args.args[0][0] === 11) {
                assert.step(args.method);
                return Promise.resolve();
            }
            return this._super.apply(this, arguments);
        }
    });

    assert.containsOnce(form, '.o_thread_snailmail_tooltip_container',
        "Snailmail icon should appear on message");
    assert.containsOnce(form, '.o_thread_message_snailmail_no_price_available',
        "Snailmail status of message should be 'no_price_available'");
    assert.containsNone(form, '.o_thread_tooltip_snailmail',
        "No tooltip should be present");

    testUtils.dom.triggerMouseEvent(form.$('.o_thread_message_snailmail_no_price_available'), 'mouseenter');
    assert.ok($('.o_thread_tooltip_snailmail:visible').length,
        "Tooltip should appear when hovering the Snailmail Icon");
    assert.ok($('.o_thread_tooltip_snailmail_icon.fa-exclamation').length,
        "Tooltip should show correct icon");
    assert.ok($('.o_thread_tooltip_snailmail:contains("Error")').length,
        "Tooltip should show correct text");

    await testUtils.dom.click(form.$('.o_thread_message_snailmail_no_price_available'));
    var $modal = $('.modal');
    assert.ok($modal.length, "A modal should open on click");

    assert.containsOnce($modal, 'button:contains("Cancel letter")',
        "Modal should have a 'Cancel letter' button");
    var $cancelButton = $('.modal').find('button:contains("Cancel letter")');
    await testUtils.dom.click($cancelButton);
    assert.notOk($('.modal').length,
        "The modal should be closed after click on 'Cancel letter'");

    assert.verifySteps(['cancel_letter'],
        "Should have made a RPC call to 'cancel_letter'");

    form.destroy();
});
示例#19
0
QUnit.test('fold Support channel', function (assert) {
    assert.expect(11);

    var messagingMenu = new MessagingMenu();
    addMockSupportEnvironment(messagingMenu, {
        data: this.data,
        mockRPC: function (route, args) {
            if (!_.string.endsWith(route, '.png')) { // ignore images
                assert.step(args.method || route);
            }
            return this._super.apply(this, arguments);
        },
        mockSupportRPC: function (route) {
            if (route.split('/')[1] === 'odoo_im_support') {
                assert.step('cors: ' + route);
            }
            return this._super.apply(this, arguments);
        },
        services: this.services,
        session: this.supportParams,
    });
    testUtils.mock.intercept(messagingMenu, 'call_service', function (ev) {
        if (ev.data.service === 'local_storage') {
            assert.step('LocalStorage: ' + ev.data.method + ' ' + ev.data.args);
        }
    }, true);
    messagingMenu.appendTo($('#qunit-fixture'));

    testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
    assert.containsOnce(messagingMenu, '.o_mail_systray_dropdown_bottom .o_mail_preview[data-preview-id=SupportChannel]');

    testUtils.dom.click(messagingMenu.$('.o_mail_preview[data-preview-id=SupportChannel]'));
    assert.strictEqual($('.o_thread_window').length, 1,
        "should have open a chat window");

    // fold, re-open and close channel
    testUtils.dom.click($('.o_thread_window .o_thread_window_title'));
    testUtils.dom.click($('.o_thread_window .o_thread_window_title'));
    testUtils.dom.click($('.o_thread_window .o_thread_window_close'));

    assert.verifySteps([
        '/mail/init_messaging',
        'message_fetch',
        'cors: /odoo_im_support/get_support_channel',
        'LocalStorage: setItem im_support.channel_state,open',
        'cors: /odoo_im_support/fetch_messages',
        'LocalStorage: setItem im_support.channel_state,folded',
        'LocalStorage: setItem im_support.channel_state,open',
        'LocalStorage: setItem im_support.channel_state,closed',
    ]);

    messagingMenu.destroy();
});
示例#20
0
    QUnit.test('click on an option should toggle options and item states properly', function (assert) {
        assert.expect(22);

        this.items[0].options = [{optionId: 1, description: "First Option"}, {optionId: 2, description: "Second Option"}];

        var eventNumber = 0;

        var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items, {
            intercepts: {
                menu_item_toggled: function (ev) {
                    eventNumber++;
                    if (eventNumber === 1) {
                        assert.strictEqual(ev.data.itemId, 1);
                        assert.strictEqual(ev.data.isActive, true);
                        assert.strictEqual(ev.data.optionId, 1);
                    } else {
                        assert.strictEqual(ev.data.itemId, 1);
                        assert.strictEqual(ev.data.isActive, false);
                        assert.strictEqual(ev.data.optionId, false);
                    }
                },
                item_option_changed: function (ev) {
                    if (eventNumber === 1) {
                        assert.strictEqual(ev.data.itemId, 1);
                        assert.strictEqual(ev.data.isActive, true);
                        assert.strictEqual(ev.data.optionId, 2);
                    }
                },
            },
        });
        // open dropdown menu
        testUtils.dom.click(dropdownMenu.$('button:first'));
        // open options menu
        testUtils.dom.click(dropdownMenu.$('span.fa-caret-right'));
        assert.containsN(dropdownMenu, '.dropdown-divider, .dropdown-item, .dropdown-item-text', 7);
        // Don't forget there is a hidden li.divider element at first place among children
        assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:nth-child(2) > .dropdown-item'), 'selected');
        assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(2) > .dropdown-item'), 'selected');
        assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(3) > .dropdown-item'), 'selected');
        testUtils.dom.click(dropdownMenu.$('.o_item_option:first'));
        assert.hasClass(dropdownMenu.$('.o_menu_item:nth-child(2) > .dropdown-item'), 'selected');
        assert.hasClass(dropdownMenu.$('.o_item_option:nth-child(2) > .dropdown-item'), 'selected');
        assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(3) > .dropdown-item'), 'selected');
        testUtils.dom.click(dropdownMenu.$('.o_item_option:nth-child(3)'));
        assert.hasClass(dropdownMenu.$('.o_menu_item:nth-child(2) > .dropdown-item'), 'selected');
        assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(2) > .dropdown-item'), 'selected');
        assert.hasClass(dropdownMenu.$('.o_item_option:nth-child(3) > .dropdown-item'), 'selected');
        testUtils.dom.click(dropdownMenu.$('.o_item_option:nth-child(3)'));
        assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:nth-child(2) > .dropdown-item'), 'selected');
        assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(2) > .dropdown-item'), 'selected');
        assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(3) > .dropdown-item'), 'selected');
        dropdownMenu.destroy();
    });
示例#21
0
    QUnit.test('mobile grouped rendering', function (assert) {
        assert.expect(11);

        var kanban = createView({
            View: KanbanView,
            model: 'partner',
            data: this.data,
            arch: '<kanban class="o_kanban_test o_kanban_small_column" on_create="quick_create">' +
                    '<templates><t t-name="kanban-box">' +
                        '<div><field name="foo"/></div>' +
                    '</t></templates>' +
                '</kanban>',
            domain: [['product_id', '!=', false]],
            groupBy: ['product_id'],
        });

        // basic rendering tests
        assert.containsN(kanban, '.o_kanban_group', 2, "should have 2 columns" );
        assert.hasClass(kanban.$('.o_kanban_mobile_tab:first'),'o_current',
            "first tab is the active tab with class 'o_current'");
        assert.hasClass(kanban.$('.o_kanban_group:first'),'o_current',
            "first column is the active column with class 'o_current'");
        assert.containsN(kanban, '.o_kanban_group:first > div.o_kanban_record', 2,
            "there are 2 records in active tab");
        assert.strictEqual(kanban.$('.o_kanban_group:nth(1) > div.o_kanban_record').length, 0,
            "there is no records in next tab. Records will be loaded when it will be opened");

        // quick create in first column
        testUtils.dom.click(kanban.$buttons.find('.o-kanban-button-new'));
        assert.hasClass(kanban.$('.o_kanban_group:nth(0) > div:nth(1)'),'o_kanban_quick_create',
            "clicking on create should open the quick_create in the first column");

        // move to second column
        kanban.$('.o_kanban_mobile_tab:nth(1)').trigger('click');
        assert.hasClass(kanban.$('.o_kanban_mobile_tab:nth(1)'),'o_current',
            "second tab is now active with class 'o_current'");
        assert.hasClass(kanban.$('.o_kanban_group:nth(1)'),'o_current',
            "second column is now active with class 'o_current'");
        assert.strictEqual(kanban.$('.o_kanban_group:nth(1) > div.o_kanban_record').length, 2,
            "the 2 records of the second group have now been loaded");

        // quick create in second column
        testUtils.dom.click(kanban.$buttons.find('.o-kanban-button-new'));
        assert.hasClass(kanban.$('.o_kanban_group:nth(1) >  div:nth(1)'),'o_kanban_quick_create',
            "clicking on create should open the quick_create in the second column");

        // kanban column should match kanban mobile tabs
        var column_ids = kanban.$('.o_kanban_group').map(function(){ return $(this).data('id') }).get();
        var tab_ids = kanban.$('.o_kanban_mobile_tab').map(function(){ return $(this).data('id') }).get();
        assert.deepEqual(column_ids, tab_ids, "all columns data-id should match mobile tabs data-id");

        kanban.destroy();
    });
QUnit.test('activity menu widget: activity view icon', function (assert) {
    assert.expect(10);
    var self = this;
    var activityMenu = new ActivityMenu();
    testUtils.mock.addMockEnvironment(activityMenu, {
        services: this.services,
        mockRPC: function (route, args) {
            if (args.method === 'systray_get_activities') {
                return $.when(self.data['mail.activity.menu'].records);
            }
            return this._super(route, args);
        },
    });
    activityMenu.appendTo($('#qunit-fixture'));
    assert.containsN(activityMenu, '.o_mail_activity_action', 2,
                       "widget should have 2 activity view icons");

    var $first = activityMenu.$('.o_mail_activity_action').eq(0);
    var $second = activityMenu.$('.o_mail_activity_action').eq(1);
    assert.strictEqual($first.data('model_name'), "Issue",
                       "first activity action should link to 'Issue'");
    assert.hasClass($first,'fa-clock-o', "should display the activity action icon");

    assert.strictEqual($second.data('model_name'), "Note",
                       "Second activity action should link to 'Note'");
    assert.hasClass($second,'fa-clock-o', "should display the activity action icon");

    testUtils.mock.intercept(activityMenu, 'do_action', function (ev) {
        if (ev.data.action.name) {
            assert.ok(ev.data.action.context, "should define a context on the action");
            assert.ok(ev.data.action.context.search_default_activities_my,
                "should auto-set search to 'My Activities' in the context of the action");
            assert.step('do_action:' + ev.data.action.name);
        } else {
            assert.step('do_action:' + ev.data.action);
        }
    }, true);

    // click on the "Issue" activity icon
    testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
    testUtils.dom.click(activityMenu.$(".o_mail_activity_action[data-model_name='Issue']"));

    // click on the "Note" activity icon
    testUtils.dom.click(activityMenu.$(".o_mail_activity_action[data-model_name='Note']"));

    assert.verifySteps([
        'do_action:Issue',
        'do_action:mail.mail_activity_type_view_tree'
    ]);

    activityMenu.destroy();
});
示例#23
0
        QUnit.test('media dialog: icon', async function (assert) {
            assert.expect(1);

            var form = await testUtils.createView({
                View: FormView,
                model: 'note.note',
                data: this.data,
                arch: '<form>' +
                    '<field name="body" widget="html" style="height: 100px"/>' +
                    '</form>',
                res_id: 1,
                mockRPC: function (route, args) {
                    if (args.model === 'ir.attachment') {
                        return Promise.resolve([]);
                    }
                    return this._super(route, args);
                },
            });
            await testUtils.form.clickEdit(form);
            var $field = form.$('.oe_form_field[name="body"]');

            // the dialog load some xml assets
            var defMediaDialog = testUtils.makeTestPromise();
            testUtils.mock.patch(MediaDialog, {
                init: function () {
                    this._super.apply(this, arguments);
                    this.opened(defMediaDialog.resolve.bind(defMediaDialog));
                }
            });

            var pText = $field.find('.note-editable p').first().contents()[0];
            Wysiwyg.setRange(pText, 1);

            $field.find('.note-toolbar .note-insert button:has(.fa-file-image-o)').mousedown().click();

            // load static xml file (dialog, media dialog, unsplash image widget)
            await defMediaDialog;
            $('.modal .tab-content .tab-pane').removeClass('fade'); // to be sync in test
            await testUtils.dom.click($('.modal a[aria-controls="editor-media-icon"]'));
            await testUtils.dom.click($('.modal #editor-media-icon .font-icons-icon.fa-glass'));
            await testUtils.dom.click($('.modal .modal-footer button.btn-primary'));

            var $editable = form.$('.oe_form_field[name="body"] .note-editable');

            assert.strictEqual($editable.data('wysiwyg').getValue(),
                '<p>t<span class="fa fa-glass"></span>oto toto toto</p><p>tata</p>',
                "should have the image in the dom");

            testUtils.mock.unpatch(MediaDialog);

            form.destroy();
        });
示例#24
0
    QUnit.test('click on an item should not change url', function (assert) {
        assert.expect(0);

        var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items);
        testUtils.dom.click(dropdownMenu.$('.o_dropdown_toggler_btn'));
        dropdownMenu.$el.click(function () {
            // we do not want a click to get out and change the url, for example
            throw new Error('No click should get out of the dropdown menu');
        });
        testUtils.dom.click(dropdownMenu.$('.o_menu_item a').first());

        dropdownMenu.destroy();
    });
    QUnit.test('Display a question', function (assert) {
        var done = assert.async();
        assert.expect(8);

        var view = createView(this.viewParams);
        function notification (inc) {
            return {
                title: 'a' + inc,
                message: 'b' + inc,
                buttons: [
                    {
                        text: 'accept' + inc,
                        primary: true,
                        click: function () {
                            assert.step('accept' + inc);
                        },
                    },
                    {
                        text: 'refuse' + inc,
                        click: function () {
                            assert.step('refuse' + inc);
                        },
                    }
                ],
                onClose: function () {
                    assert.step('close' + inc);
                }
            };
        };
        view.call('notification', 'notify', notification(0));
        view.call('notification', 'notify', notification(1));
        view.call('notification', 'notify', notification(2));

        var $notification = $('body .o_notification_manager .o_notification');
        assert.strictEqual($notification.eq(0).find('.o_close').length, 1, "should display the close button in notification");
        assert.strictEqual(_.str.trim($notification.eq(0).html().replace(/\s+/g, ' ')),
            "<a aria-label=\"Close\" class=\"fa fa-times o_close\" href=\"#\" title=\"Close\"></a> <div class=\"o_notification_title\"> <span role=\"img\" aria-label=\"Notification undefined\" class=\"o_icon fa fa-3x fa-question-circle-o\" title=\"Notification undefined\"></span> a0 </div> <div class=\"o_notification_content\">b0</div> <div class=\"o_buttons\"> <button class=\"btn btn-primary\" type=\"button\"> <span>accept0</span> </button><button class=\"btn btn-secondary\" type=\"button\"> <span>refuse0</span> </button> </div>",
            "should display notification");

        testUtils.dom.click($notification.find('.o_buttons button:contains(accept0)'));
        testUtils.dom.click($notification.find('.o_buttons button:contains(refuse1)'));
        testUtils.dom.click($notification.eq(2).find('.o_close'));

        setTimeout(function () {
            assert.strictEqual($notification.is(':hidden'), true, "should hide the notification");
            assert.strictEqual($('body .o_notification_manager .o_notification').length, 0, "should destroy the notification");
            assert.verifySteps(['accept0', 'refuse1', 'close2']);
            view.destroy();
            done();
        });
    });
示例#26
0
QUnit.test('messaging menu widget: open inbox for needaction not linked to any document', async function (assert) {
    assert.expect(4);

    var messagingMenu = new MessagingMenu();
    testUtils.mock.addMockEnvironment(messagingMenu, {
        services: this.services,
        data: this.data,
        session: {
            partner_id: 1,
        },
    });
    await messagingMenu.appendTo($('#qunit-fixture'));

    // Simulate received needaction message without associated document,
    // so that we have a message in inbox without a model and a resID
    var message = {
        id: 2,
        author_id: [1, "Me"],
        body: '<p>test</p>',
        channel_ids: [],
        needaction_partner_ids: [1],
    };
    var notifications = [
        [['myDB', 'ir.needaction'], message]
    ];
    messagingMenu.call('bus_service', 'trigger', 'notification', notifications);

    // Open messaging menu
    await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));

    var $firstChannelPreview =
        messagingMenu.$('.o_mail_preview').first();

    assert.strictEqual($firstChannelPreview.length, 1,
        "should have at least one channel preview");
    assert.strictEqual($firstChannelPreview.data('preview-id'),
        'mailbox_inbox',
        "should be a preview from channel inbox");

    testUtils.mock.intercept(messagingMenu, 'do_action', function (ev) {
        if (ev.data.action === 'mail.action_discuss') {
            assert.step('do_action:' + ev.data.action + ':' + ev.data.options.active_id);
        }
    }, true);
    await testUtils.dom.click($firstChannelPreview);
    assert.verifySteps(
        ['do_action:mail.action_discuss:mailbox_inbox'],
        "should open Discuss with Inbox");

    messagingMenu.destroy();
});
示例#27
0
QUnit.test('save to dashboard actions with flag keepSearchView', function (assert) {
    assert.expect(4);

    var actionManager = createActionManager({
        data: this.data,
        archs: {
            'partner,false,graph': '<graph><field name="foo"/></graph>',
            'partner,false,list': '<list><field name="foo"/></list>',
            'partner,false,search': '<search></search>',
        },
        mockRPC: function (route, args) {
            if (route === '/board/add_to_dashboard') {
                assert.strictEqual(args.action_id, 2,
                    "should save the correct action");
                assert.strictEqual(args.view_mode, 'graph',
                    "should save the correct view type");
                return $.when(true);
            }
            return this._super.apply(this, arguments);
        },
    });

    // execute a first action
    actionManager.doAction({
        id: 1,
        res_model: 'partner',
        type: 'ir.actions.act_window',
        views: [[false, 'list']],
    });

    // execute another action with flag 'keepSearchView' and add it to dashboard
    var options = {keepSearchView: true};
    actionManager.doAction({
        id: 2,
        res_model: 'partner',
        type: 'ir.actions.act_window',
        views: [[false, 'graph']],
    }, options);

    assert.containsOnce(actionManager, '.o_graph',
        "should display the graph view");
    assert.strictEqual($('.o_add_to_dashboard_link').length, 1,
        "should allow the 'Add to dashboard' feature (this is the same searchview)");

    // add this action to dashboard
    testUtils.dom.click($('.o_search_options .o_dropdown button:contains(Favorites)'));
    testUtils.dom.click($('.o_add_to_dashboard_link'));
    testUtils.dom.click($('.o_add_to_dashboard_button'));

    actionManager.destroy();
});
示例#28
0
    QUnit.test("form: Manage Attachments option", async function (assert) {
        assert.expect(3);

        var debugManager = createDebugManager({
            intercepts: {
                do_action: function (event) {
                    assert.deepEqual(event.data.action, {
                      context: {
                        default_res_model: "test.model",
                        default_res_id: 5,
                      },
                      domain: [["res_model", "=", "test.model"],["res_id", "=", 5]],
                      name: "Manage Attachments",
                      res_model: "ir.attachment",
                      type: "ir.actions.act_window",
                      views: [[false, "list"],[false, "form"]],
                    });
                },
            },
        });
        await debugManager.appendTo($('#qunit-fixture'));

        // Simulate update debug manager from web client
        var action = {
            views: [{
                displayName: "Form",
                fieldsView: {
                    view_id: 2,
                },
                type: "form",
            }],
            res_model: "test.model",
        };
        var view = {
            viewType: "form",
            getSelectedIds: function () {
                return [5];
            },
        };
        await debugManager.update('action', action, view);

        var $attachmentMenu = debugManager.$('a[data-action=get_attachments]');
        assert.strictEqual($attachmentMenu.length, 1, "should have Manage Attachments menu item");
        assert.strictEqual($attachmentMenu.text().trim(), "Manage Attachments",
            "should have correct menu item text");
        await testUtils.dom.click(debugManager.$('> a')); // open dropdown
        await testUtils.dom.click($attachmentMenu);

        debugManager.destroy();
    });
示例#29
0
        return concurrency.delay(0).then(function () {
            // need to set the measure this way because it cannot be set in the
            // arch.
            testUtils.dom.click(graph.$buttons.find('.dropdown-toggle:contains(Measures)'));
            testUtils.dom.click(graph.$buttons.find('.dropdown-item[data-field="product_id"]'));

            assert.strictEqual(graph.model.chart.data[0].value, 1,
                "should have first datapoint with value 1");
            assert.strictEqual(graph.model.chart.data[1].value, 1,
                "should have second datapoint with value 1");

            graph.destroy();
            done();
        });
示例#30
0
    QUnit.test('Display a question', async function (assert) {
        assert.expect(8);

        var view = await createView(this.viewParams);
        function notification (inc) {
            return {
                title: 'a' + inc,
                message: 'b' + inc,
                buttons: [
                    {
                        text: 'accept' + inc,
                        primary: true,
                        click: function () {
                            assert.step('accept' + inc);
                        },
                    },
                    {
                        text: 'refuse' + inc,
                        click: function () {
                            assert.step('refuse' + inc);
                        },
                    }
                ],
                onClose: function () {
                    assert.step('close' + inc);
                }
            };
        };
        view.call('notification', 'notify', notification(0));
        view.call('notification', 'notify', notification(1));
        view.call('notification', 'notify', notification(2));
        await testUtils.nextTick();

        var $notification = $('body .o_notification_manager .o_notification');
        assert.containsOnce($notification.eq(0), '.o_notification_close',
            "should display the close button in notification");
        assert.strictEqual(_.str.trim($notification.eq(0).html().replace(/\s+/g, ' ')),
            "<div class=\"toast-header\"> <span role=\"img\" aria-label=\"Notification undefined\" class=\"fa fa-2x mr-3 fa-question-circle-o o_notification_icon\" title=\"Notification undefined\"></span> <div class=\"d-flex align-items-center mr-auto font-weight-bold o_notification_title\">a0</div> <button aria-label=\"Close\" class=\"mb-1 close o_notification_close\" data-dismiss=\"toast\" type=\"button\"> <span aria-hidden=\"true\" class=\"d-inline\">×</span> </button> </div> <div class=\"toast-body\"> <div class=\"o_notification_content\">b0</div> <div class=\"mt-2 o_notification_buttons\"> <button class=\"btn btn-primary\" type=\"button\"> <span>accept0</span> </button><button class=\"btn btn-secondary\" type=\"button\"> <span>refuse0</span> </button> </div> </div>",
            "should display notification");

        testUtils.dom.click($notification.find('.o_notification_buttons button:contains(accept0)'));
        testUtils.dom.click($notification.find('.o_notification_buttons button:contains(refuse1)'));
        testUtils.dom.click($notification.eq(2).find('.o_notification_close'));

        assert.strictEqual($notification.is(':hidden'), true, "should hide the notification");
        assert.strictEqual($('body .o_notification_manager .o_notification').length,
            0, "should destroy the notification");
        assert.verifySteps(['accept0', 'refuse1', 'close2']);
        view.destroy();
    });