forked from Mapan/odoo17e
137 lines
6.2 KiB
Python
137 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import base64
|
|
import datetime
|
|
import random
|
|
|
|
from unittest.mock import patch
|
|
|
|
from odoo import fields
|
|
from odoo.addons.base.tests.test_ir_cron import CronMixinCase
|
|
from odoo.addons.social.tests.common import SocialCase
|
|
from odoo.addons.social.models.social_post import SocialPost
|
|
from odoo.addons.social_push_notifications.models.social_account import SocialAccountPushNotifications
|
|
|
|
|
|
class SocialPushNotificationsCase(SocialCase, CronMixinCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(SocialPushNotificationsCase, cls).setUpClass()
|
|
|
|
cls.website_1 = cls.env['website'].create({
|
|
'name': 'Website 1 WITHOUT push notifications',
|
|
'domain': 'website1.example.com',
|
|
'firebase_enable_push_notifications': False,
|
|
})
|
|
cls.website_2 = cls.env['website'].create({
|
|
'name': 'Website 2 WITH push notifications',
|
|
'domain': 'website2.example.com',
|
|
'firebase_enable_push_notifications': True,
|
|
'firebase_use_own_account': True,
|
|
'firebase_admin_key_file': base64.b64encode(b'{}')
|
|
})
|
|
cls.website_3 = cls.env['website'].create({
|
|
'name': 'Website 3 WITH push notifications',
|
|
'domain': 'website3.example.com',
|
|
'firebase_enable_push_notifications': True,
|
|
'firebase_use_own_account': True,
|
|
'firebase_admin_key_file': base64.b64encode(b'{}')
|
|
})
|
|
cls.websites = cls.website_1 | cls.website_2 | cls.website_3
|
|
|
|
cls.social_accounts = cls.env['social.account'].search(
|
|
[('website_id', 'in', cls.websites.ids)]
|
|
)
|
|
|
|
cls.social_post.invalidate_model(['account_allowed_ids'])
|
|
cls.social_post.write({
|
|
'account_ids': [(6, 0, cls.social_accounts.filtered(lambda a: a.website_id.id != cls.website_3.id).ids)],
|
|
})
|
|
|
|
def test_post(self):
|
|
""" Test a full flow of posting social_push_notifications.
|
|
We trigger the send method of the post and check that it does all the way to the Firebase
|
|
sending calls. """
|
|
|
|
# Create some visitors with or without push_token in different timezone (or no timezone)
|
|
timezones = ['Europe/Brussels', 'America/New_York', 'Asia/Vladivostok', False]
|
|
Visitor = self.env['website.visitor']
|
|
visitor_vals = []
|
|
for i in range(0, 4):
|
|
visitor_vals.append({
|
|
'name': timezones[i] or 'Visitor',
|
|
'timezone': timezones[i],
|
|
'access_token': '%032x' % random.randrange(16**32),
|
|
'push_subscription_ids': [(0, 0, {'push_token': 'fake_token_%s' % i})] if i != 0 else False,
|
|
'website_id': self.websites[i].id if i != 3 else False,
|
|
})
|
|
self.visitors = Visitor.create(visitor_vals)
|
|
self.social_post.create_uid.write({'tz': timezones[0]})
|
|
|
|
# Since mocking a decorated method doesn't work, we unset the constrains
|
|
# before creating the post and re-apply them after.
|
|
check_scheduled_date_constrains = SocialPost._check_scheduled_date._constrains
|
|
SocialPost._check_scheduled_date._constrains = tuple()
|
|
|
|
scheduled_date = fields.Datetime.now() - datetime.timedelta(minutes=1)
|
|
with self.capture_triggers('social.ir_cron_post_scheduled') as captured_triggers:
|
|
self.social_post.write({
|
|
'use_visitor_timezone': True,
|
|
'post_method': 'scheduled',
|
|
'scheduled_date': scheduled_date
|
|
})
|
|
|
|
SocialPost._check_scheduled_date._constrains = check_scheduled_date_constrains
|
|
|
|
# when scheduling, a CRON trigger is created to match the scheduled_date
|
|
self.assertEqual(len(captured_triggers.records), 1)
|
|
captured_trigger = captured_triggers.records[0]
|
|
self.assertEqual(captured_trigger.call_at, scheduled_date)
|
|
self.assertEqual(captured_trigger.cron_id, self.env.ref('social.ir_cron_post_scheduled'))
|
|
|
|
self.assertEqual(self.social_post.state, 'draft')
|
|
|
|
with self.capture_triggers('social.ir_cron_post_scheduled') as captured_triggers:
|
|
self.social_post._action_post() # begin the post process
|
|
|
|
# as the post_method is 'scheduled', a CRON trigger should not be created, we already have one
|
|
self.assertEqual(len(captured_triggers.records), 0)
|
|
|
|
# check that live posts are correctly created
|
|
live_posts = self.env['social.live.post'].search([('post_id', '=', self.social_post.id)])
|
|
self.assertEqual(len(live_posts), 2)
|
|
|
|
self.assertTrue(all(live_post.state == 'ready' for live_post in live_posts))
|
|
self.assertEqual(self.social_post.state, 'posting')
|
|
|
|
def _firebase_send_message_from_configuration(_this, _data, visitors):
|
|
website = visitors.website_id
|
|
push_enabled = website.firebase_enable_push_notifications
|
|
# Ensure that only visitors from the website with push notifications enabled
|
|
# and linked to the social account are notified
|
|
self.assertEqual(len(visitors), 1 if push_enabled else 0)
|
|
if visitors:
|
|
self.assertEqual(visitors.website_id, self.website_2)
|
|
return visitors.mapped('push_subscription_ids.push_token'), []
|
|
|
|
with patch.object(SocialAccountPushNotifications, '_firebase_send_message_from_configuration',
|
|
_firebase_send_message_from_configuration):
|
|
live_posts._post_push_notifications()
|
|
|
|
self.assertFalse(all(live_post.state == 'posted' for live_post in live_posts))
|
|
self.assertEqual(self.social_post.state, 'posting')
|
|
|
|
# simulate that everyone can receive the push notif (because their time >= time of the one who created the post)
|
|
self.visitors.write({'timezone': self.env.user.tz})
|
|
|
|
with patch.object(SocialAccountPushNotifications, '_firebase_send_message_from_configuration',
|
|
_firebase_send_message_from_configuration):
|
|
live_posts._post_push_notifications()
|
|
|
|
self._checkPostedStatus(True)
|
|
|
|
@classmethod
|
|
def _get_social_media(cls):
|
|
return cls.env.ref('social_push_notifications.social_media_push_notifications')
|