odoo.define('mail/static/src/components/follower/follower_tests.js', function (require) {
'use strict';

const components = {
    Follower: require('mail/static/src/components/follower/follower.js'),
};
const { makeDeferred } = require('mail/static/src/utils/deferred/deferred.js');
const {
    afterEach,
    afterNextRender,
    beforeEach,
    createRootComponent,
    start,
} = require('mail/static/src/utils/test_utils.js');

const Bus = require('web.Bus');

QUnit.module('mail', {}, function () {
QUnit.module('components', {}, function () {
QUnit.module('follower', {}, function () {
QUnit.module('follower_tests.js', {
    beforeEach() {
        beforeEach(this);

        this.createFollowerComponent = async (follower) => {
            await createRootComponent(this, components.Follower, {
                props: { followerLocalId: follower.localId },
                target: this.widget.el,
            });
        };

        this.start = async params => {
            const { env, widget } = await start(Object.assign({}, params, {
                data: this.data,
            }));
            this.env = env;
            this.widget = widget;
        };
    },
    afterEach() {
        afterEach(this);
    },
});

QUnit.test('base rendering not editable', async function (assert) {
    assert.expect(5);

    await this.start();

    const thread = this.env.models['mail.thread'].create({
        id: 100,
        model: 'res.partner',
    });
    const follower = await this.env.models['mail.follower'].create({
        channel: [['insert', { id: 1, model: 'mail.channel', name: "François Perusse" }]],
        followedThread: [['link', thread]],
        id: 2,
        isActive: true,
        isEditable: false,
    });
    await this.createFollowerComponent(follower);
    assert.containsOnce(
        document.body,
        '.o_Follower',
        "should have follower component"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_details',
        "should display a details part"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_avatar',
        "should display the avatar of the follower"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_name',
        "should display the name of the follower"
    );
    assert.containsNone(
        document.body,
        '.o_Follower_button',
        "should have no button as follower is not editable"
    );
});

QUnit.test('base rendering editable', async function (assert) {
    assert.expect(6);

    await this.start();
    const thread = this.env.models['mail.thread'].create({
        id: 100,
        model: 'res.partner',
    });
    const follower = await this.env.models['mail.follower'].create({
        channel: [['insert', { id: 1, model: 'mail.channel', name: "François Perusse" }]],
        followedThread: [['link', thread]],
        id: 2,
        isActive: true,
        isEditable: true,
    });
    await this.createFollowerComponent(follower);
    assert.containsOnce(
        document.body,
        '.o_Follower',
        "should have follower component"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_details',
        "should display a details part"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_avatar',
        "should display the avatar of the follower"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_name',
        "should display the name of the follower"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_editButton',
        "should have an edit button"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_removeButton',
        "should have a remove button"
    );
});

QUnit.test('click on channel follower details', async function (assert) {
    assert.expect(7);

    const bus = new Bus();
    bus.on('do-action', null, payload => {
        assert.step('do_action');
        assert.strictEqual(
            payload.action.res_id,
            10,
            "The redirect action should redirect to the right res id (10)"
        );
        assert.strictEqual(
            payload.action.res_model,
            'mail.channel',
            "The redirect action should redirect to the right res model (mail.channel)"
        );
        assert.strictEqual(
            payload.action.type,
            "ir.actions.act_window",
            "The redirect action should be of type 'ir.actions.act_window'"
        );
    });
    this.data['res.partner'].records.push({ id: 100 });
    this.data['mail.channel'].records.push({ id: 10 });
    await this.start({
        env: { bus },
    });
    const thread = this.env.models['mail.thread'].create({
        id: 100,
        model: 'res.partner',
    });
    const follower = await this.env.models['mail.follower'].create({
        channel: [['insert', { id: 10, model: 'mail.channel', name: "channel" }]],
        followedThread: [['link', thread]],
        id: 2,
        isActive: true,
        isEditable: true,
    });
    await this.createFollowerComponent(follower);
    assert.containsOnce(
        document.body,
        '.o_Follower',
        "should have follower component"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_details',
        "should display a details part"
    );

    document.querySelector('.o_Follower_details').click();
    assert.verifySteps(
        ['do_action'],
        "clicking on channel should redirect to channel form view"
    );
});

QUnit.test('click on partner follower details', async function (assert) {
    assert.expect(7);

    const openFormDef = makeDeferred();
    const bus = new Bus();
    bus.on('do-action', null, payload => {
        assert.step('do_action');
        assert.strictEqual(
            payload.action.res_id,
            3,
            "The redirect action should redirect to the right res id (3)"
        );
        assert.strictEqual(
            payload.action.res_model,
            'res.partner',
            "The redirect action should redirect to the right res model (res.partner)"
        );
        assert.strictEqual(
            payload.action.type,
            "ir.actions.act_window",
            "The redirect action should be of type 'ir.actions.act_window'"
        );
        openFormDef.resolve();
    });
    this.data['res.partner'].records.push({ id: 100 });
    await this.start({
        env: { bus },
    });
    const thread = this.env.models['mail.thread'].create({
        id: 100,
        model: 'res.partner',
    });
    const follower = await this.env.models['mail.follower'].create({
        followedThread: [['link', thread]],
        id: 2,
        isActive: true,
        isEditable: true,
        partner: [['insert', {
            email: "bla@bla.bla",
            id: this.env.messaging.currentPartner.id,
            name: "François Perusse",
        }]],
    });
    await this.createFollowerComponent(follower);
    assert.containsOnce(
        document.body,
        '.o_Follower',
        "should have follower component"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_details',
        "should display a details part"
    );

    document.querySelector('.o_Follower_details').click();
    await openFormDef;
    assert.verifySteps(
        ['do_action'],
        "clicking on follower should redirect to partner form view"
    );
});

QUnit.test('click on edit follower', async function (assert) {
    assert.expect(5);

    this.data['res.partner'].records.push({ id: 100, message_follower_ids: [2] });
    this.data['mail.followers'].records.push({
        id: 2,
        is_active: true,
        is_editable: true,
        partner_id: this.data.currentPartnerId,
        res_id: 100,
        res_model: 'res.partner',
    });
    await this.start({
        hasDialog: true,
        async mockRPC(route, args) {
            if (route.includes('/mail/read_subscription_data')) {
                assert.step('fetch_subtypes');
            }
            return this._super(...arguments);
        },
    });
    const thread = this.env.models['mail.thread'].create({
        id: 100,
        model: 'res.partner',
    });
    await thread.refreshFollowers();
    await this.createFollowerComponent(thread.followers[0]);
    assert.containsOnce(
        document.body,
        '.o_Follower',
        "should have follower component"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_editButton',
        "should display an edit button"
    );

    await afterNextRender(() => document.querySelector('.o_Follower_editButton').click());
    assert.verifySteps(
        ['fetch_subtypes'],
        "clicking on edit follower should fetch subtypes"
    );
    assert.containsOnce(
        document.body,
        '.o_FollowerSubtypeList',
        "A dialog allowing to edit follower subtypes should have been created"
    );
});

QUnit.test('edit follower and close subtype dialog', async function (assert) {
    assert.expect(6);

    this.data['res.partner'].records.push({ id: 100 });
    await this.start({
        hasDialog: true,
        async mockRPC(route, args) {
            if (route.includes('/mail/read_subscription_data')) {
                assert.step('fetch_subtypes');
                return [{
                    default: true,
                    followed: true,
                    internal: false,
                    id: 1,
                    name: "Dummy test",
                    res_model: 'res.partner'
                }];
            }
            return this._super(...arguments);
        },
    });
    const thread = this.env.models['mail.thread'].create({
        id: 100,
        model: 'res.partner',
    });
    const follower = await this.env.models['mail.follower'].create({
        followedThread: [['link', thread]],
        id: 2,
        isActive: true,
        isEditable: true,
        partner: [['insert', {
            email: "bla@bla.bla",
            id: this.env.messaging.currentPartner.id,
            name: "François Perusse",
        }]],
    });
    await this.createFollowerComponent(follower);
    assert.containsOnce(
        document.body,
        '.o_Follower',
        "should have follower component"
    );
    assert.containsOnce(
        document.body,
        '.o_Follower_editButton',
        "should display an edit button"
    );

    await afterNextRender(() => document.querySelector('.o_Follower_editButton').click());
    assert.verifySteps(
        ['fetch_subtypes'],
        "clicking on edit follower should fetch subtypes"
    );
    assert.containsOnce(
        document.body,
        '.o_FollowerSubtypeList',
        "dialog allowing to edit follower subtypes should have been created"
    );

    await afterNextRender(
        () => document.querySelector('.o_FollowerSubtypeList_closeButton').click()
    );
    assert.containsNone(
        document.body,
        '.o_DialogManager_dialog',
        "follower subtype dialog should be closed after clicking on close button"
    );
});

});
});
});

});
