Пример #1
0
    QUnit.test('Display a sticky notification with onClose callback', function (assert) {
        var done = assert.async();
        assert.expect(2);

        testUtils.mock.unpatch(Notification);
        testUtils.mock.patch(Notification, {
            _autoCloseDelay: 2500,
            _animationDelay: 0,
        });
        var view = createView(this.viewParams);

        var close = 0;
        view.call('notification', 'notify', {
            title: 'a',
            message: 'b',
            sticky: true,
            onClose: function () {
                close++;
            }
        });
        assert.strictEqual(close, 0, "should wait to call onClose method once");
        testUtils.dom.click($('body .o_notification_manager .o_notification .o_close'));
        setTimeout(function () {
            assert.strictEqual(close, 1, "should call onClose method once");
            view.destroy();
            done();
        });
    });
Пример #2
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();
    });
Пример #3
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();
});
Пример #4
0
QUnit.test('activity menu widget: activity menu with 3 records', 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.hasClass(activityMenu.$el, 'o_mail_systray_item', 'should be the instance of widget');
    // the assertion below has not been replace because there are includes of ActivityMenu that modify the length.
    assert.ok(activityMenu.$('.o_mail_preview').length);
    assert.containsOnce(activityMenu.$el, '.o_notification_counter', "widget should have notification counter");
    assert.strictEqual(parseInt(activityMenu.el.innerText), 8, "widget should have 8 notification counter");

    var context = {};
    testUtils.mock.intercept(activityMenu, 'do_action', function (event) {
        assert.deepEqual(event.data.action.context, context, "wrong context value");
    }, true);

    // case 1: click on "late"
    context = {
        search_default_activities_overdue: 1,
    };
    testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
    assert.hasClass(activityMenu.$el, 'show', 'ActivityMenu should be open');
    testUtils.dom.click(activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='overdue']"));
    assert.doesNotHaveClass(activityMenu.$el, 'show', 'ActivityMenu should be closed');
    // case 2: click on "today"
    context = {
        search_default_activities_today: 1,
    };
    testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
    testUtils.dom.click(activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='today']"));
    // case 3: click on "future"
    context = {
        search_default_activities_upcoming_all: 1,
    };
    testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
    testUtils.dom.click(activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='upcoming_all']"));
    // case 4: click anywere else
    context = {
        search_default_activities_overdue: 1,
        search_default_activities_today: 1,
    };
    testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
    testUtils.dom.click(activityMenu.$(".o_mail_systray_dropdown_items > div[data-model_name='Issue']"));

    activityMenu.destroy();
});
Пример #5
0
QUnit.test('dashboard intercepts custom events triggered by sub controllers', function (assert) {
    assert.expect(4);

    // we patch the ListController to force it to trigger the custom events that
    // we want the dashboard to intercept (to stop them or to tweak their data)
    testUtils.mock.patch(ListController, {
        start: function () {
            this.trigger_up('update_filters');
            this.trigger_up('env_updated');
            this.do_action({}, {keepSearchView: true});
        },
    });

    var board = createView({
        View: BoardView,
        model: 'board',
        data: this.data,
        arch: '<form string="My Dashboard">' +
                '<board style="2-1">' +
                    '<column>' +
                        '<action context="{}" view_mode="list" string="ABC" name="51" domain="[]"></action>' +
                    '</column>' +
                '</board>' +
            '</form>',
        mockRPC: function (route) {
            if (route === '/web/action/load') {
                return $.when({res_model: 'partner', views: [[false, 'list']]});
            }
            return this._super.apply(this, arguments);
        },
        archs: {
            'partner,false,list': '<tree string="Partner"/>',
        },
        intercepts: {
            do_action: function (ev) {
                assert.strictEqual(ev.data.options.keepSearchView, false,
                    "the 'keepSearchView' options should have been set to false");
            },
            env_updated: function (ev) {
                assert.strictEqual(ev.target.modelName, 'board',
                    "env_updated event should be triggered by the dashboard itself");
                assert.step('env_updated');
            },
            update_filters: assert.step.bind(assert, 'update_filters'),
        },
    });

    assert.verifySteps([
        'env_updated', // triggered by the dashboard itself
    ]);

    testUtils.mock.unpatch(ListController);
    board.destroy();
});
Пример #6
0
    QUnit.test('provide notification ID of 0 by default', function (assert) {
        // This test is important in order to ensure that we provide the correct
        // sentinel value 0 when we are not aware of the last notification ID
        // that we have received. We cannot provide an ID of -1, otherwise it
        // may likely be handled incorrectly (before this test was written,
        // it was providing -1 to the server, which in return sent every stored
        // notifications related to this user).
        assert.expect(3);

        // Simulate no ID of last notification in the local storage
        testUtils.mock.patch(LocalStorageServiceMock, {
            getItem: function (key) {
                if (key === 'last_ts') {
                    return 0;
                }
                return this._super.apply(this, arguments);
            },
        });

        var pollDeferred = $.Deferred();
        var parent = new Widget();
        testUtils.mock.addMockEnvironment(parent, {
            data: {},
            services: {
                bus_service: BusService,
                local_storage: LocalStorageServiceMock,
            },
            mockRPC: function (route, args) {
                if (route === '/longpolling/poll') {
                    assert.step(route);
                    assert.strictEqual(args.last, 0,
                        "provided last notification ID should be 0");

                    pollDeferred = $.Deferred();
                    pollDeferred.abort = (function () {
                        this.reject({message: "XmlHttpRequestError abort"}, $.Event());
                    }).bind(pollDeferred);
                    return pollDeferred;
                }
                return this._super.apply(this, arguments);
            }
        });

        var widget = new Widget(parent);
        widget.appendTo($('#qunit-fixture'));

        // trigger longpolling poll RPC
        widget.call('bus_service', 'addChannel', 'lambda');
        assert.verifySteps(['/longpolling/poll']);

        testUtils.mock.unpatch(LocalStorageServiceMock);
        parent.destroy();
    });
Пример #7
0
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();
});
Пример #8
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();
        });
Пример #9
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();
});
Пример #10
0
QUnit.test('Format Error', async function (assert) {
    assert.expect(8);

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

    testUtils.mock.patch(ThreadWidget, {
        do_action: function (action, options) {
            assert.step("do_action");
        },
    });

    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_format_error',
        "Snailmail status of message should be 'format_error'");
    assert.containsNone(form, '.o_thread_tooltip_snailmail',
        "No tooltip should be present");

    testUtils.dom.triggerMouseEvent(form.$('.o_thread_message_snailmail_format_error'), '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_format_error'));
    assert.verifySteps(['do_action'], "'do_action' should have been called");

    form.destroy();
    testUtils.mock.unpatch(ThreadWidget);
});
Пример #11
0
QUnit.test('messaging menu widget: messaging menu with 1 record', async function (assert) {
    assert.expect(3);
    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.containsOnce(messagingMenu, '.o_mail_preview',
        "should display a preview");
    assert.strictEqual(messagingMenu.$('.o_preview_name').text().trim(), "general",
        "should display correct name of channel in preview");

    // remove any space-character inside text
    var lastMessagePreviewText =
        messagingMenu.$('.o_last_message_preview').text().replace(/\s/g, "");
    assert.strictEqual(lastMessagePreviewText,
        "Me:test",
        "should display correct last message preview in channel preview");

    messagingMenu.destroy();
});
Пример #12
0
        QUnit.test('drag&drop snippet', 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" options="{\'snippets\': \'web_editor.snippets\'}"/>' +
                    '</form>',
                res_id: 1,
            });
            var defSnippets = testUtils.makeTestPromise();
            testUtils.mock.intercept(form, "snippets_loaded", function () {
                defSnippets.resolve();
            });

            await testUtils.form.clickEdit(form);
            var $field = form.$('.oe_form_field[name="body"]');
            var $editable = $field.find('.note-editable');

            await defSnippets;
            var $hr = $field.find('.oe_snippet_thumbnail:first');
            testUtils.dom.dragAndDrop($hr, $editable.find('p'));

            assert.strictEqual($editable.data('wysiwyg').getValue().replace(/\s+/g, ' '),
                '<div class=\"s_hr pt32 pb32\"> <hr class=\"s_hr_1px s_hr_solid w-100 mx-auto\"> </div><p>toto toto toto</p><p>tata</p>',
                "should drop the snippet");

            form.destroy();
        });
Пример #13
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();
    });
Пример #14
0
    QUnit.test("creating a domain with a default option", function (assert) {
        assert.expect(1);

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

        // Create the domain selector and its mock environment
        var domainSelector = new DomainSelector(null, "partner", [], {
            readonly: false,
            debugMode: true,
            default: [["foo","=","kikou"]],
        });
        testUtils.mock.addMockEnvironment(domainSelector, {data: this.data});
        domainSelector.appendTo($target);

        // Clicking on the button should add a visible field selector in the
        // widget so that the user can change the field chain
        testUtils.dom.click(domainSelector.$(".o_domain_add_first_node_button:visible"));

        assert.strictEqual(
            domainSelector.$(".o_domain_debug_input").val(),
            '[["foo","=","kikou"]]',
            "the domain input should contain the default domain");

        domainSelector.destroy();
    });
Пример #15
0
QUnit.test('messaging menu widget: rendering with OdooBot has a request', function (assert) {
    assert.expect(5);

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

    assert.containsOnce(messagingMenu, '.o_notification_counter',
        "should display a notification counter next to the messaging menu");
    assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '1',
        "should display a counter of '1' next to the messaging menu");

    testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
    assert.containsOnce(messagingMenu, '.o_preview_info',
        "should display a preview in the messaging menu");
    assert.strictEqual(messagingMenu.$('.o_preview_name').text().trim(),
        'OdooBot has a request',
        "preview should display that OdooBot has a request");
    assert.strictEqual(messagingMenu.$('.o_preview_counter').text().replace(/\s/g, ''),
        '(1)', "should display an counter of '1' next to the preview");

    messagingMenu.destroy();
});
Пример #16
0
    QUnit.test('settings view shows statusbar buttons only if there are changes to save', function (assert) {
        assert.expect(5);

        var form = createView({
            View: BaseSettingsView,
            model: 'project',
            data: this.data,
            arch: '<form string="Settings" class="oe_form_configuration o_base_settings">' +
                    '<header>' +
                        '<button string="Save" type="object" name="execute" class="oe_highlight" />' +
                        '<button string="Discard" type="object" name="cancel" special="cancel" />'+
                    '</header>' +
                    '<div class="o_setting_container">' +
                        '<div class="settings_tab"/>' +
                        '<div class="settings">' +
                            '<div class="notFound o_hidden">No Record Found</div>' +
                            '<div class="app_settings_block" string="Base Setting" data-key="base-setting">' +
                                '<field name="bar"/>Make Changes' +
                            '</div>' +
                        '</div>' +
                    '</div>' +
                '</form>',
        });

        testUtils.mock.intercept(form, "field_changed", function (event) {
            assert.ok("field changed");
        }, true);

        assert.containsNone(form, '.o_field_boolean input:checked', "checkbox should not be checked");
        assert.hasClass(form.$('.o_statusbar_buttons'), 'd-none', "statusbar buttons should not be shown");
        testUtils.dom.click(form.$("input[type='checkbox']"));
        assert.strictEqual(form.$('.o_field_boolean input:checked').length, 1,"checkbox should be checked");
        assert.isVisible(form.$('.o_statusbar_buttons'), "statusbar buttons should be shown");
        form.destroy();
    });
Пример #17
0
    QUnit.test('Attendance Kiosk Mode Test', async function (assert) {
        assert.expect(2);

        var $target = $('#qunit-fixture');
        var self = this;
        var rpcCount = 0;
        var clientAction = new KioskMode(null, {});
        testUtils.mock.addMockEnvironment(clientAction, {
            data: this.data,
            session: {
                uid: 1,
                company_id: 1,
            },
            mockRPC: function(route, args) {
                if (args.method === 'attendance_scan' && args.model === 'hr.employee') {

                    rpcCount++;
                    return Promise.resolve(self.data['hr.employee'].records[0]);
                }
                return this._super(route, args);
            },
        });
        await clientAction.appendTo($target);
        core.bus.trigger('barcode_scanned', 1);
        core.bus.trigger('barcode_scanned', 1);
        assert.strictEqual(rpcCount, 1, 'RPC call should have been done only once.');

        core.bus.trigger('barcode_scanned', 2);
        assert.strictEqual(rpcCount, 1, 'RPC call should have been done only once.');

        clientAction.destroy();
    });
Пример #18
0
    QUnit.test("default `showSearchInput` option", function (assert) {
        assert.expect(6);

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

        // Create the field selector and its mock environment
        var fieldSelector = new ModelFieldSelector(null, "partner", [], {
            readonly: false,
        });
        testUtils.mock.addMockEnvironment(fieldSelector, {data: this.data});
        fieldSelector.appendTo($target);

        fieldSelector.$el.trigger('focusin');
        var $fieldSelectorPopover = fieldSelector.$(".o_field_selector_popover:visible");
        var $searchInput = $fieldSelectorPopover.find(".o_field_selector_search input");
        assert.strictEqual($searchInput.length, 1, "there should be a search input");

        // without search
        assert.strictEqual($fieldSelectorPopover.find("li").length, 3, "there should be three available fields");
        assert.strictEqual($fieldSelectorPopover.find("li").text().trim().replace(/\s+/g, ' '), "Bar Foo Product", "the available field should be correct");
        $searchInput.val('xx').trigger('keyup');

        assert.strictEqual($fieldSelectorPopover.find("li").length, 0, "there shouldn't be any element");
        $searchInput.val('Pro').trigger('keyup');
        assert.strictEqual($fieldSelectorPopover.find("li").length, 1, "there should only be one element");
        assert.strictEqual($fieldSelectorPopover.find("li").text().trim().replace(/\s+/g, ' '), "Product", "the available field should be the Product");

        fieldSelector.destroy();
    });
Пример #19
0
    QUnit.test('formviewdialog buttons in footer are positioned properly', function (assert) {
        assert.expect(2);

        var parent = createParent({
            data: this.data,
            archs: {
                'partner,false,form':
                    '<form string="Partner">' +
                        '<sheet>' +
                            '<group><field name="foo"/></group>' +
                            '<footer><button string="Custom Button" type="object" class="btn-primary"/></footer>' +
                        '</sheet>' +
                    '</form>',
            },
        });

        testUtils.mock.intercept(parent, 'env_updated', function () {
            throw new Error("The environment should not be propagated to the action manager");
        });


        new dialogs.FormViewDialog(parent, {
            res_model: 'partner',
            res_id: 1,
        }).open();

        assert.notOk($('.modal-body button').length,
            "should not have any button in body");
        assert.strictEqual($('.modal-footer button').length, 1,
            "should have only one button in footer");
        parent.destroy();
    });
Пример #20
0
        async function createGreetingMessage (target, barcode){
            var action = {
                attendance: {
                    check_in: "2018-09-20 13:41:13",
                    employee_id: [barcode],
                },
                next_action: "hr_attendance.hr_attendance_action_kiosk_mode",
                barcode: barcode,
            };
            var clientAction = new GreetingMessage(null, action);
            testUtils.mock.addMockEnvironment(clientAction, {
                data: self.data,
                session: {
                    uid: 1,
                    company_id: 1,
                },
                mockRPC: function(route, args) {
                    if (args.method === 'attendance_scan' && args.model === 'hr.employee') {
                        rpcCount++;
                        action.attendance.employee_id = [args.args[0], 'Employee'];
                        /*
                            if rpc have been made, a new instance is created to simulate the same behaviour
                            as functional flow.
                        */
                        createGreetingMessage (target, args.args[0]);
                        return Promise.resolve({action: action});
                    }
                    return this._super(route, args);
                },
            });
            await clientAction.appendTo(target);

            clientActions.push(clientAction);
        }
Пример #21
0
QUnit.test('dashboard: click on a button to execute an action', function (assert) {
    assert.expect(2);

    var dashboard_data = this.dashboard_data;
    var kanban = createView({
        View: view_registry.get('sales_team_dashboard'),
        model: 'partner',
        data: this.data,
        arch: '<kanban class="o_kanban_test">' +
                '<templates><t t-name="kanban-box">' +
                    '<div>' +
                        '<button name="func_name" String="A" type="object" class="my_button"/>' +
                        '<field name="foo"/>' +
                    '</div>' +
                '</t></templates>' +
              '</kanban>',
        mockRPC: function (route, args) {
            if (args.method === 'retrieve_sales_dashboard') {
                return Promise.resolve(dashboard_data);
            }
            return this._super(route, args);
        },
    });


    testUtils.mock.intercept(kanban, 'execute_action', function (event) {
        assert.strictEqual(event.data.action_data.name, 'func_name',
            'execute_action should have been triggered with the correct data');
        assert.strictEqual(event.data.action_data.type, 'object',
            'execute_action should have been triggered with the correct data');
    });

    testUtils.dom.click(kanban.$('.my_button:first()'));
    kanban.destroy();
});
Пример #22
0
/**
 * Test Utils
 *
 * In this module, we define some utility functions to create mock objects
 * in the mail module, such as the BusService or Discuss.
 */

/**
 * Create asynchronously a discuss widget.
 * This is async due to mail_manager/mail_service that needs to be ready.
 *
 * @param {Object} params
 * @return {$.Promise} resolved with the discuss widget
 */
function createDiscuss(params) {
    var Parent = Widget.extend({
        do_push_state: function () {},
    });
    var parent = new Parent();
    params.archs = params.archs || {
        'mail.message,false,search': '<search/>',
    };
    testUtils.mock.addMockEnvironment(parent, params);
    var discuss = new Discuss(parent, params);
    discuss.set_cp_bus(new Widget());
    var selector = params.debug ? 'body' : '#qunit-fixture';
    var controlPanel = new ControlPanel(parent);
    controlPanel.appendTo($(selector));

    // override 'destroy' of discuss so that it calls 'destroy' on the parent
    // instead, which is the parent of discuss and the mockServer.
    discuss.destroy = function () {
        // remove the override to properly destroy discuss and its children
        // when it will be called the second time (by its parent)
        delete discuss.destroy;
        parent.destroy();
    };

    // link the view to the control panel
    discuss.set_cp_bus(controlPanel.get_bus());

    return  discuss.appendTo($(selector)).then(function () {
        return discuss;
    });
}
Пример #23
0
function createGroupByMenu(groupBys, fields, params) {
    params = params || {};
    var target = params.debug ? document.body :  $('#qunit-fixture');
    var menu = new GroupByMenu(null, groupBys, fields);
    testUtils.mock.addMockEnvironment(menu, params);
    menu.appendTo(target);
    return menu;
}
Пример #24
0
 afterEach: function () {
     // The Notification Service has a side effect: it adds a div inside
     // document.body.  We could implement a cleanup mechanism for services,
     // but this seems a little overkill since services are not supposed to
     // be destroyed anyway.
     $('.o_notification_manager').remove();
     testUtils.mock.unpatch(Notification);
 }
Пример #25
0
function createDropdownMenu(dropdownTitle, groups, params) {
    params = params || {};
    var target = params.debug ? document.body :  $('#qunit-fixture');
    var menu = new DropdownMenu(null, dropdownTitle, groups);
    testUtils.mock.addMockEnvironment(menu, params);
    menu.appendTo(target);
    return menu;
}
Пример #26
0
QUnit.test('needaction messages in channels should appear, in addition to channel preview', async function (assert) {
    // Let's suppose a channel whose before-last message (msg1) is a needaction,
    // but not the last message (msg2). In that case, the systray messaging
    // menu should display the needaction message msg1 in the preview, and the
    // channel preview with the msg2.
    assert.expect(3);

    // simulate a needaction (mention) message in channel 'general'
    var partnerID = 44;
    var needactionMessage = {
        author_id: [1, "Demo"],
        body: "<p>@Administrator: ping</p>",
        channel_ids: [1],
        id: 3,
        model: 'mail.channel',
        needaction: true,
        needaction_partner_ids: [partnerID],
        record_name: 'general',
        res_id: 1,
    };
    var lastMessage = {
        author_id: [2, "Other"],
        body: "<p>last message content</p>",
        channel_ids: [1],
        id: 4,
        model: 'mail.channel',
        record_name: 'general',
        res_id: 1,
    };
    this.data['mail.message'].records = [needactionMessage, lastMessage];

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

    await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));

    assert.containsN(messagingMenu, '.o_mail_preview', 2,
        "should display two previews");
    var $preview1 = messagingMenu.$('.o_mail_preview').eq(0);
    var $preview2 = messagingMenu.$('.o_mail_preview').eq(1);

    assert.strictEqual($preview1.find('.o_last_message_preview').text().replace(/\s/g, ""),
        "Demo:@Administrator:ping",
        "1st preview (needaction preview) should display needaction message");
    assert.strictEqual($preview2.find('.o_last_message_preview').text().replace(/\s/g, ""),
        "Other:lastmessagecontent",
        "2nd preview (channel preview) should display last message preview");

    messagingMenu.destroy();
});
Пример #27
0
 return wysiwyg.attachTo($textarea).then(function () {
     if (wysiwygOptions.snippets) {
         var defSnippets = $.Deferred();
         testUtils.mock.intercept(wysiwyg, "snippets_loaded", function () {
             defSnippets.resolve(wysiwyg);
         });
         return defSnippets;
     }
     return wysiwyg;
 });
Пример #28
0
QUnit.test('subviews are aware of attach in or detach from the DOM', function (assert) {
    assert.expect(2);

    // patch list renderer `on_attach_callback` for the test only
    testUtils.mock.patch(ListRenderer, {
        on_attach_callback: function () {
            assert.step('subview on_attach_callback');
        }
    });

    var form = createView({
        View: BoardView,
        model: 'board',
        data: this.data,
        arch: '<form string="My Dashboard">' +
                '<board style="2-1">' +
                    '<column>' +
                        '<action context="{}" view_mode="list" string="ABC" name="51" domain="[]"></action>' +
                    '</column>' +
                '</board>' +
            '</form>',
        mockRPC: function (route) {
            if (route === '/web/action/load') {
                return $.when({
                    res_model: 'partner',
                    views: [[4, 'list']],
                });
            }
            return this._super.apply(this, arguments);
        },
        archs: {
            'partner,4,list':
                '<list string="Partner"><field name="foo"/></list>',
        },
    });

    assert.verifySteps(['subview on_attach_callback']);

    // restore on_attach_callback of ListRenderer
    testUtils.mock.unpatch(ListRenderer);

    form.destroy();
});
Пример #29
0
    QUnit.test('notifications received from the longpolling channel', function (assert) {
        assert.expect(6);

        var pollDeferred = $.Deferred();

        var parent = new Widget();
        testUtils.mock.addMockEnvironment(parent, {
            data: {},
            services: {
                bus_service: BusService,
                local_storage: LocalStorageServiceMock,
            },
            mockRPC: function (route, args) {
                if (route === '/longpolling/poll') {
                    assert.step([route, args.channels.join(',')]);

                    pollDeferred = $.Deferred();
                    pollDeferred.abort = (function () {
                        this.reject({message: "XmlHttpRequestError abort"}, $.Event());
                    }).bind(pollDeferred);
                    return pollDeferred;
                }
                return this._super.apply(this, arguments);
            }
        });

        var widget = new Widget(parent);
        widget.appendTo($('#qunit-fixture'));

        widget.call('bus_service', 'onNotification', this, function (notifications) {
            assert.step(['notification', notifications]);
        });
        widget.call('bus_service', 'addChannel', 'lambda');

        pollDeferred.resolve([{
            id: 1,
            channel: 'lambda',
            message: 'beta',
        }]);
        pollDeferred.resolve([{
            id: 2,
            channel: 'lambda',
            message: 'epsilon',
        }]);

        assert.verifySteps([
            ["/longpolling/poll", "lambda"],
            ["notification", [["lambda","beta"]]],
            ["/longpolling/poll", "lambda"],
            ["notification", [["lambda","epsilon"]]],
            ["/longpolling/poll", "lambda"]
        ]);

        parent.destroy();
    });
Пример #30
0
QUnit.test('open, fold, unfold and close a document thread window', function (assert) {
    assert.expect(8);

    var messagingMenu = new MessagingMenu();
    testUtils.mock.addMockEnvironment(messagingMenu, {
        services: this.services,
        data: this.data,
        session: this.session,
    });
    testUtils.mock.intercept(messagingMenu, 'call_service', function (ev) {
        if (ev.data.service === 'local_storage' && ev.data.method === 'setItem') {
            assert.step(ev.data.args);
        }
    }, true);
    messagingMenu.appendTo($('#qunit-fixture'));

    // toggle the messaging menu and open the documentThread
    testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
    assert.containsOnce(messagingMenu, '.o_mail_preview',
        "should display one preview");
    testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
    assert.strictEqual($('.o_thread_window').length, 1,
        "should have open the DocumentThread in a thread window");
    assert.strictEqual($('.o_thread_window .o_thread_message').length, 2,
        "should display 2 messages in the thread window");

    // fold and unfold thread window
    testUtils.dom.click($('.o_thread_window .o_thread_window_title'));
    testUtils.dom.click($('.o_thread_window .o_thread_window_title'));

    // close thread window
    testUtils.dom.click($('.o_thread_window .o_thread_window_close'));

    assert.verifySteps([
        ['mail.document_threads_state', {"some.res.model_1": {"name": "Some Record", "windowState": "open"}}],
        ['mail.document_threads_state', {"some.res.model_1": {"name": "Some Record", "windowState": "folded"}}],
        ['mail.document_threads_state', {"some.res.model_1": {"name": "Some Record", "windowState": "open"}}],
        ['mail.document_threads_state', {"some.res.model_1": {"name": "Some Record", "windowState": "closed"}}],
    ]);

    messagingMenu.destroy();
});