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();
});
QUnit.test("messaging menu widget: mark as read on thread preview", function ( assert ) {
    assert.expect(8);

    testUtils.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.addMockEnvironment(messagingMenu, {
        services: this.services,
        data: this.data,
    });

    messagingMenu.appendTo($('#qunit-fixture'));
    messagingMenu.$('.dropdown-toggle').click();
    assert.ok(messagingMenu.$el.hasClass('o_mail_systray_item'),
        'should be the instance of widget');
    assert.ok(messagingMenu.$el.hasClass('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.strictEqual(messagingMenu.$('.o_mail_preview_mark_as_read').length, 1,
        "should have mark as read icon next to preview");

    messagingMenu.$(".o_mail_preview_mark_as_read").click();

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

    testUtils.unpatch(DocumentThread);
    messagingMenu.destroy();
});
Esempio n. 3
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.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.unpatch(ListController);
    board.destroy();
});
Esempio n. 4
0
QUnit.test('activity menu widget: activity menu with 3 records', function (assert) {
    assert.expect(10);
    var self = this;
    var activityMenu = new systray.ActivityMenu();
    testUtils.addMockEnvironment(activityMenu, {
        services: this.services,
        mockRPC: function (route, args) {
            if (args.method === 'activity_user_count') {
                return $.when(self.data['mail.activity.menu']['records']);
            }
            return this._super(route, args);
        },
    });
    activityMenu.appendTo($('#qunit-fixture'));
    assert.ok(activityMenu.$el.hasClass('o_mail_navbar_item'), 'should be the instance of widget');
    assert.ok(activityMenu.$('.o_mail_channel_preview').hasClass('o_mail_channel_preview'), "should instance of widget");
    assert.ok(activityMenu.$('.o_notification_counter').hasClass('o_notification_counter'), "widget should have notification counter");
    assert.strictEqual(parseInt(activityMenu.el.innerText), 5, "widget should have 5 notification counter");

    var context = {};
    testUtils.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,
    };
    activityMenu.$('.dropdown-toggle').click();
    assert.strictEqual(activityMenu.$el.hasClass("open"), true, 'ActivityMenu should be open');
    activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='overdue']").click();
    assert.strictEqual(activityMenu.$el.hasClass("open"), false, 'ActivityMenu should be closed');
    // case 2: click on "today"
    context = {
        search_default_activities_today: 1,
    };
    activityMenu.$('.dropdown-toggle').click();
    activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='today']").click();
    // case 3: click on "future"
    context = {
        search_default_activities_upcoming_all: 1,
    };
    activityMenu.$('.dropdown-toggle').click();
    activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='upcoming_all']").click();
    // case 4: click anywere else
    context = {
        search_default_activities_overdue: 1,
        search_default_activities_today: 1,
    };
    activityMenu.$('.dropdown-toggle').click();
    activityMenu.$(".o_mail_navbar_dropdown_channels > div[data-model_name='Issue']").click();

    activityMenu.destroy();
});
Esempio n. 5
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();
        });
Esempio n. 6
0
    QUnit.test("calling _rpc on destroyed widgets", async function (assert) {
        assert.expect(3);

        var def;
        var parent = new Widget();
        testUtils.mock.addMockEnvironment(parent, {
            session: {
                rpc: function () {
                    def = testUtils.makeTestPromise();
                    def.abort = def.reject;
                    return def;
                },
            },
            services: {
                ajax: AjaxService
            },
        });
        var widget = new Widget(parent);

        widget._rpc({route: '/a/route'}).then(function () {
            assert.ok(true, "The ajax call should be resolve");
        });
        def.resolve();
        await testUtils.nextMicrotaskTick();
        def = null;

        widget._rpc({route: '/a/route'}).then(function () {
            throw Error("Calling _rpc on a destroyed widget should return a " +
            "promise that remains pending forever");
        }).catch(function () {
            throw Error("Calling _rpc on a destroyed widget should return a " +
            "promise that remains pending forever");
        });
        widget.destroy();
        def.resolve();
        await testUtils.nextMicrotaskTick();
        def = null;

        widget._rpc({route: '/a/route'}).then(function () {
            throw Error("Calling _rpc on a destroyed widget should return a " +
                "promise that remains pending forever");
        }).catch(function () {
            throw Error("Calling _rpc on a destroyed widget should return a " +
            "promise that remains pending forever");
        });
        assert.ok(!def, "trigger_up is not performed and the call returns a " +
            "promise that remains pending forever");

        assert.ok(true,
            "there should be no crash when calling _rpc on a destroyed widget");
        parent.destroy();
    });
Esempio n. 7
0
QUnit.test('do no update form twice after a command barcode scanned', function (assert) {
    assert.expect(7);

    var delay = barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms;
    barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = 0;
    testUtils.patch(FormController, {
        update: function () {
            assert.step('update');
            return this._super.apply(this, arguments);
        },
    });

    var form = createView({
        View: FormView,
        model: 'product',
        data: this.data,
        arch: '<form>' +
                    '<field name="display_name"/>' +
                    '<field name="int_field" widget="field_float_scannable"/>' +
                '</form>',
        mockRPC: function (route, args) {
            if (args.method === 'read') {
                assert.step('read');
            }
            return this._super.apply(this, arguments);
        },
        res_id: 1,
        viewOptions: {
            ids: [1, 2],
            index: 0,
        },
    });

    assert.verifySteps(['read'], "update should not have been called yet");

    // switch to next record
    _.each(["O","-","C","M","D",".","N","E","X","T","Enter"], triggerKeypressEvent);
    // a first update is done to reload the data (thus followed by a read), but
    // update shouldn't be called afterwards
    assert.verifySteps(['read', 'update', 'read']);

    _.each(['5','4','3','9','8','2','6','7','1','2','5','2','Enter'], triggerKeypressEvent);
    // a real barcode has been scanned -> an update should be requested (with
    // option reload='false', so it isn't followed by a read)
    assert.verifySteps(['read', 'update', 'read', 'update']);

    form.destroy();
    barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = delay;
    testUtils.unpatch(FormController);
});
Esempio n. 8
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\', \'cssEdit\': \'template.assets_all_style\'}"/>' +
                    '</form>',
                res_id: 1,
            });
            var defSnippets = testUtils.makeTestPromise();
            testUtils.mock.intercept(form, "snippets_loaded", function () {
                defSnippets.resolve();
            });
            await testUtils.form.clickEdit(form);

            await defSnippets;
            var doc = form.$('iframe').contents()[0];
            var $content = $('#iframe_target', doc);
            var $editable = $content.find('.note-editable');

            var $hr = $content.find('.oe_snippet_thumbnail:first');
            var from = $hr.offset();
            var to = $editable.find('p').offset();

            $hr.trigger($.Event("mousedown", {
                which: 1,
                pageX: from.left + 1,
                pageY: from.top + 1
            }));
            $hr.trigger($.Event("mousemove", {
                which: 1,
                pageX: to.left,
                pageY: to.top
            }));
            $hr.trigger($.Event("mouseup", {
                which: 1,
                pageX: to.left,
                pageY: to.top
            }));

            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();
        });
Esempio n. 9
0
QUnit.test('html_frame does not crash when saving in readonly', function (assert) {
    // The 'Save' action may be triggered even in readonly (e.g. when clicking
    // on a button in the form view)
    assert.expect(2);

    var form = testUtils.createView({
        View: FormView,
        model: 'mass.mailing',
        data: this.data,
        arch: '<form string="Partners">' +
                '<sheet>' +
                    '<field name="body" widget="html_frame" options="{\'editor_url\': \'/logo\'}"/>' +
                '</sheet>' +
            '</form>',
        res_id: 1,
        mockRPC: function (route, args) {
            if (args.method) {
                assert.step(args.method);
            }
            if (_.str.startsWith(route, '/logo')) {
                // manually call the callback to simulate that the iframe has
                // been loaded (note: just the content, not the editor)
                window.odoo[$.deparam(route).callback + '_content'].call();
                return $.when();
            }
            return this._super.apply(this, arguments);
        },
    });

    form.saveRecord(); // before the fix done in this commit, it crashed here
    
    assert.verifySteps(['read']);

    form.destroy();
});
Esempio n. 10
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 $.when(dashboard_data);
            }
            return this._super(route, args);
        },
    });


    testUtils.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');
    });

    kanban.$('.my_button:first()').click(); // click on the button of the first card
    kanban.destroy();
});
Esempio n. 11
0
    QUnit.test("list: edit view menu item", async function (assert) {
        assert.expect(3);

        var debugManager = createDebugManager();

        debugManager.appendTo($('#qunit-fixture'));

        // Simulate update debug manager from web client
        var action = {
            views: [{
                displayName: "List",
                fieldsView: {
                    view_id: 1,
                },
                type: "list",
            }],
        };
        var view = {
            viewType: "list",
        };
        await testUtils.nextTick();
        await debugManager.update('action', action, view);

        var $editView = debugManager.$('a[data-action=edit][data-model="ir.ui.view"]');
        assert.strictEqual($editView.length, 1, "should have edit view menu item");
        assert.strictEqual($editView.text().trim(), "Edit View: List",
            "should have correct menu item text for editing view");
        assert.strictEqual($editView.data('id'), 1, "should have correct view_id");

        debugManager.destroy();
    });
Esempio n. 12
0
QUnit.test('field html widget (with options inline-style)', function (assert) {
    var done = assert.async();
    assert.expect(3);

    var form = testUtils.createView({
        View: FormView,
        model: 'mass.mailing',
        data: this.data,
        arch: '<form string="Partners">' +
                '<field name="body" widget="html" style="height: 100px" options="{\'style-inline\': true}"/>' +
            '</form>',
        res_id: 1,
    });

    assert.strictEqual(form.$('iframe').length, 1,
        "should have rendered an iframe without crashing in readonly");
    assert.strictEqual(form.$('div[name=body]').attr('style'), 'height: 100px',
        "should have applied the style correctly");

    form.$buttons.find('.o_form_button_edit').click();

    assert.strictEqual(form.$('.note-editable').html(), '<div class="field_body">yep</div>',
            "should have rendered the field correctly in edit");

    // summernote invokes handlers after a setTimeout, so we must wait as well
    // before destroying the widget (otherwise we'll have a crash later on)
    setTimeout(function () {
        form.destroy();
        done();
    }, 0);
});
Esempio n. 13
0
        QUnit.test('rendering with iframe for readonly mode', async function (assert) {
            assert.expect(3);

            var form = await testUtils.createView({
                View: FormView,
                model: 'note.note',
                data: this.data,
                arch: '<form>' +
                    '<field name="body" widget="html" style="height: 100px" options="{\'cssReadonly\': \'template.assets\'}"/>' +
                    '</form>',
                res_id: 1,
            });
            var $field = form.$('.oe_form_field[name="body"]');
            var $iframe = $field.find('iframe.o_readonly');
            await $iframe.data('loadDef');
            var doc = $iframe.contents()[0];
            assert.strictEqual($(doc).find('#iframe_target').html(),
                '<p>toto toto toto</p><p>tata</p>',
                "should have rendered a div with correct content in readonly");

            assert.strictEqual(doc.defaultView.getComputedStyle(doc.body).backgroundColor,
                'rgb(255, 0, 0)',
                "should load the asset css");

            await testUtils.form.clickEdit(form);

            $field = form.$('.oe_form_field[name="body"]');
            assert.strictEqual($field.find('.note-editable').html(),
                '<p>toto toto toto</p><p>tata</p>',
                "should have rendered the field correctly in edit");

            form.destroy();
        });
Esempio n. 14
0
    QUnit.test('Attendance Kiosk Mode Test', function (assert) {
        assert.expect(2);

        var $target = $('#qunit-fixture');
        var self = this;
        var rpcCount = 0;
        var clientAction = new KioskMode(null);
        testUtils.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 $.when(self.data['hr.employee'].records[0]);
                }
                return this._super(route, args);
            },
        });
        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();
    });
Esempio n. 15
0
QUnit.test('field htmlsimple does not crash when commitChanges is called in mode=readonly', function (assert) {
    assert.expect(1);

    var form = testUtils.createView({
        View: FormView,
        model: 'mass.mailing',
        data: this.data,
        arch: '<form string="Partners">' +
                '<header>' +
                    '<button name="some_method" class="s" string="Do it" type="object"/>' +
                '</header>' +
                '<sheet>' +
                    '<field name="body"/>' +
                '</sheet>' +
            '</form>',
        res_id: 1,
        intercepts: {
            execute_action: function () {
                assert.step('execute_action');
            }
        },
    });

    form.$('button:contains(Do it)').click();
    form.destroy();
});
Esempio n. 16
0
QUnit.test('field html_frame widget', function (assert) {
    assert.expect(6);

    var form = testUtils.createView({
        View: FormView,
        model: 'mass.mailing',
        data: this.data,
        arch: '<form string="Partners">' +
                '<field name="body" widget="html_frame" options="{\'editor_url\': \'/logo\'}"/>' +
            '</form>',
        res_id: 1,
        session: {user_context: {lang: "en_us"}},
        mockRPC: function (route) {
            if (_.str.startsWith(route, '/logo')) {
                // those tests will be executed twice, once in readonly and once in edit
                assert.ok(route.search('model=mass.mailing') > 0,
                    "the route should specify the correct model");
                assert.ok(route.search('res_id=1') > 0,
                    "the route should specify the correct id");
                return $.when();
            }
            return this._super.apply(this, arguments);
        },
    });

    assert.strictEqual(form.$('iframe').length, 1, "should have rendered an iframe without crashing");

    form.$buttons.find('.o_form_button_edit').click();

    assert.strictEqual(form.$('iframe').length, 1, "should have rendered an iframe without crashing");

    form.destroy();
});
Esempio n. 17
0
    QUnit.test('Display a custom notification', async function (assert) {
        assert.expect(3);

        var Custom = Notification.extend({
            init: function (parent, params) {
                this._super.apply(this, arguments);
                assert.ok(params.customParams, 'instantiate custom notification');
            },
            start: function () {
                var self = this;
                return this._super().then(function () {
                    self.$el.html('Custom');
                });
            },
        });

        var view = await createView(this.viewParams);
        view.call('notification', 'notify', {
            Notification: Custom,
            customParams: true,
        });
        await testUtils.nextMicrotaskTick();
        assert.containsOnce($('body'), '.o_notification_manager .o_notification:contains(Custom)',
            "should display the notification");
        view.destroy();
        assert.containsNone($('body'), '.o_notification_manager .o_notification',
            "should destroy the notification");
    });
Esempio n. 18
0
    QUnit.test('Display a sticky notification with onClose callback', async function (assert) {
        assert.expect(2);

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

        var close = 0;
        view.call('notification', 'notify', {
            title: 'a',
            message: 'b',
            sticky: true,
            onClose: function () {
                close++;
            }
        });
        await testUtils.nextMicrotaskTick();
        assert.strictEqual(close, 0, "should wait to call onClose method once");
        testUtils.dom.click($('body .o_notification_manager .o_notification .o_notification_close'));
        assert.strictEqual(close, 1, "should call onClose method once");
        view.destroy();
    });
Esempio n. 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.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($('div.modal .modal-body button').length,
            "should not have any button in body");
        assert.strictEqual($('div.modal .modal-footer button').length, 1,
            "should have only one button in footer");
        parent.destroy();
    });
Esempio n. 20
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();
    testUtils.addMockEnvironment(parent, _.extend(params, {
        archs: {
            'mail.message,false,search': '<search/>',
        },
    }));
    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;
    });
}
Esempio n. 21
0
        QUnit.test('field html translatable', async function (assert) {
            assert.expect(3);

            var multiLang = _t.database.multi_lang;
            _t.database.multi_lang = true;

            this.data['note.note'].fields.body.translate = true;

            var form = await testUtils.createView({
                View: FormView,
                model: 'note.note',
                data: this.data,
                arch: '<form string="Partners">' +
                    '<field name="body" widget="html"/>' +
                    '</form>',
                res_id: 1,
                mockRPC: function (route, args) {
                    if (route === '/web/dataset/call_button' && args.method === 'translate_fields') {
                        assert.deepEqual(args.args, ['note.note', 1, 'body', {}], "should call 'call_button' route");
                        return Promise.resolve();
                    }
                    return this._super.apply(this, arguments);
                },
            });
            assert.strictEqual(form.$('.oe_form_field_html .o_field_translate').length, 0,
                "should not have a translate button in readonly mode");

            await testUtils.form.clickEdit(form);
            var $button = form.$('.oe_form_field_html .note-toolbar .o_field_translate');
            assert.strictEqual($button.length, 1, "should have a translate button");
            $button.click();

            form.destroy();
            _t.database.multi_lang = multiLang;
        });
Esempio n. 22
0
        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",
            }
            var clientAction = new GreetingMessage(null, action);
            testUtils.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 $.when({action: action});
                    }
                    return this._super(route, args);
                },
            });
            clientAction.appendTo(target);

            clientActions.push(clientAction);
        };
Esempio n. 23
0
QUnit.test('messaging menu widget: messaging menu with 1 record', function (assert) {
    assert.expect(3);
    var messagingMenu = new MessagingMenu();
    testUtils.addMockEnvironment(messagingMenu, {
        services: this.services,
        data: this.data,
    });
    messagingMenu.appendTo($('#qunit-fixture'));

    messagingMenu.$('.dropdown-toggle').click();

    assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 1,
        "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();
});
Esempio n. 24
0
QUnit.test('html_frame saving in edit mode (editor and content fully loaded)', function (assert) {
    var done = assert.async();
    assert.expect(4);

    var editorBar = new web_editor.Class();
    var loadDeferred = $.Deferred();
    var writeDeferred = $.Deferred();

    var form = testUtils.createView({
        View: FormView,
        model: 'mass.mailing',
        data: this.data,
        arch: '<form string="Partners">' +
                '<sheet>' +
                    '<field name="display_name"/>' +
                    '<field name="body" widget="html_frame" options="{\'editor_url\': \'/logo\'}"/>' +
                '</sheet>' +
            '</form>',
        res_id: 1,
        mockRPC: function (route, args) {
            if (args.method) {
                assert.step(args.method);
                if (args.method === 'write') {
                    writeDeferred.resolve();    
                }
            }
            if (_.str.startsWith(route, '/logo')) {
                // manually call the callback to simulate that the iframe has
                // been fully loaded (content + editor)
                var callback = $.deparam(route).callback;
                return loadDeferred.then(function () {
                    var contentCallback = window.odoo[callback + '_content'];
                    var editorCallback = window.odoo[callback + '_editor'];
                    if (editorCallback && contentCallback) {
                        contentCallback();
                        editorCallback(editorBar);
                    }
                });
            }
            return this._super.apply(this, arguments);
        },
    });

    form.$buttons.find('.o_form_button_edit').click();
    form.$('input').val('trululu').trigger('input');
    form.$buttons.find('.o_form_button_save').click();

    loadDeferred.resolve(); // simulate late loading of html frame

    assert.strictEqual(form.$('.o_field_char').val(), 'trululu',
        "should have saved the char field text");

    writeDeferred.then( function () { // html_frame is async with write
        assert.verifySteps(['read', 'write']);
        form.destroy();
        done();
    });

});
Esempio n. 25
0
function createFiltersMenu(filters, fields, params) {
    params = params || {};
    var target = params.debug ? document.body :  $('#qunit-fixture');
    var menu = new FiltersMenu(null, filters, fields);
    testUtils.addMockEnvironment(menu, params);
    menu.appendTo(target);
    return menu;
}
Esempio n. 26
0
QUnit.test('needaction messages in channels should appear, in addition to channel preview', 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.addMockEnvironment(messagingMenu, {
        services: this.services,
        data: this.data,
        session: {
            partner_id: partnerID,
        },
    });
    messagingMenu.appendTo($('#qunit-fixture'));

    messagingMenu.$('.dropdown-toggle').click();

    assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 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();
});
Esempio n. 27
0
    QUnit.skip('Display a simple notification with onClose callback when automatically close', async function (assert) {
        assert.expect(2);

        var close = 0;
        var view = await createView(this.viewParams);
        view.call('notification', 'notify', {
            title: 'a',
            message: 'b',
            onClose: function () {
                close++;
            }
        });
        await testUtils.nextMicrotaskTick();
        view.destroy();
        assert.strictEqual(close, 0, "should wait to call onClose method once");
        await testUtils.nextTick();
        assert.strictEqual(close, 1, "should call onClose method once");
    });
Esempio n. 28
0
QUnit.test('messaging menu widget: no crash when clicking on inbox notification not associated to a document', function (assert) {
    assert.expect(3);

    var messagingMenu = new MessagingMenu();
    testUtils.addMockEnvironment(messagingMenu, {
        services: this.services,
        data: this.data,
        session: {
            partner_id: 1,
        },
        intercepts: {
            /**
             * Simulate action 'mail.action_discuss' successfully performed.
             *
             * @param {OdooEvent} ev
             * @param {function} ev.data.on_success called when success action performed
             */
            do_action: function (ev) {
                ev.data.on_success();
            },
        },
    });
    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
    messagingMenu.$('.dropdown-toggle').click();

    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");
    try {
        $firstChannelPreview.click();
        assert.ok(true, "should not have crashed when clicking on needaction preview message");
    } finally {
        messagingMenu.destroy();
    }
});
Esempio n. 29
0
        function createParent(params) {
            var widget = new Widget();

            widget.on('get_emojis', widget, function (ev) {
                ev.data.callback([]);
            });

            testUtils.addMockEnvironment(widget, params);
            return widget;
        }
Esempio n. 30
0
QUnit.test('do not crash when destroyed between start en end of _renderSearchView', function (assert) {
    assert.expect(2);
    var discuss;

    testUtils.patch(Discuss, {
        init: function () {
            discuss = this;
            this._super.apply(this, arguments);
        },
    });

    var def = $.Deferred();

    testUtils.patch(SearchView, {
        willStart: function () {
            var result = this._super.apply(this, arguments);
            return def.then($.when(result));
        },
    });

    createDiscuss({
        id: 1,
        context: {},
        params: {},
        data: this.data,
        services: this.services,
        mockRPC: function (route, args) {
            if (args.method) {
                assert.step(args.method);
            }
            return this._super.apply(this, arguments);
        },
    });

    discuss.destroy();
    def.resolve();
    assert.verifySteps([
        "load_views",
    ]);

    testUtils.unpatch(Discuss);
    testUtils.unpatch(SearchView);
});