# Copyright 2018 ACSONE SA/NV # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). import json from werkzeug.urls import url_encode from odoo.tests import HttpCase from odoo.tests.common import HOST from odoo.tools import config, mute_logger class TestController(HttpCase): def url_open_json(self, url, json): return self.opener.post( "http://{}:{}{}".format(HOST, config["http_port"], url), json=json ) def _check_all_partners(self, all_partners, companies_only=False): domain = [] if companies_only: domain.append(("is_company", "=", True)) expected_names = set(self.env["res.partner"].search(domain).mapped("name")) actual_names = {r["name"] for r in all_partners} self.assertEqual(actual_names, expected_names) def test_get(self): self.authenticate("admin", "admin") query = "{allPartners{name}}" data = {"query": query} r = self.url_open("/graphql/demo?" + url_encode(data)) self.assertEqual(r.status_code, 200) self.assertEqual(r.headers["Content-Type"], "application/json") self._check_all_partners(r.json()["data"]["allPartners"]) def test_get_with_variables(self): self.authenticate("admin", "admin") query = """ query myQuery($companiesOnly: Boolean) { allPartners(companiesOnly: $companiesOnly) { name } } """ variables = {"companiesOnly": True} data = {"query": query, "variables": json.dumps(variables)} r = self.url_open("/graphql/demo?" + url_encode(data)) self.assertEqual(r.status_code, 200) self.assertEqual(r.headers["Content-Type"], "application/json") self._check_all_partners(r.json()["data"]["allPartners"], companies_only=True) def test_post_form(self): self.authenticate("admin", "admin") query = "{allPartners{name}}" data = {"query": query} r = self.url_open("/graphql/demo", data=data) self.assertEqual(r.status_code, 200) self.assertEqual(r.headers["Content-Type"], "application/json") self._check_all_partners(r.json()["data"]["allPartners"]) def test_post_form_with_variables(self): self.authenticate("admin", "admin") query = """ query myQuery($companiesOnly: Boolean) { allPartners(companiesOnly: $companiesOnly) { name } } """ variables = {"companiesOnly": True} data = {"query": query, "variables": json.dumps(variables)} r = self.url_open("/graphql/demo", data=data) self.assertEqual(r.status_code, 200) self.assertEqual(r.headers["Content-Type"], "application/json") self._check_all_partners(r.json()["data"]["allPartners"], companies_only=True) def test_post_json_with_variables(self): self.authenticate("admin", "admin") query = """ query myQuery($companiesOnly: Boolean) { allPartners(companiesOnly: $companiesOnly) { name } } """ variables = {"companiesOnly": True} data = {"query": query, "variables": variables} r = self.url_open_json("/graphql/demo", data) self.assertEqual(r.status_code, 200) self.assertEqual(r.headers["Content-Type"], "application/json") self._check_all_partners(r.json()["data"]["allPartners"], companies_only=True) def test_post_form_mutation(self): self.authenticate("admin", "admin") query = """ mutation { createPartner( name: "Le Héro, Toto", email: "toto@example.com" ) { name } } """ data = {"query": query} r = self.url_open("/graphql/demo", data=data) self.assertEqual(r.status_code, 200) self.assertEqual(r.headers["Content-Type"], "application/json") self.assertEqual("Le Héro, Toto", r.json()["data"]["createPartner"]["name"]) self.assertEqual( len(self.env["res.partner"].search([("email", "=", "toto@example.com")])), 1 ) def test_get_mutation_not_allowed(self): """ Cannot perform a mutation with a GET, must use POST. """ self.authenticate("admin", "admin") query = """ mutation { createPartner( name: "Le Héro, Toto", email: "toto@example.com" ) { name } } """ data = {"query": query} r = self.url_open("/graphql/demo?" + url_encode(data)) self.assertEqual(r.status_code, 405) self.assertEqual(r.headers["Content-Type"], "application/json") self.assertIn( "Can only perform a mutation operation from a POST request.", r.json()["errors"][0]["message"], ) @mute_logger("graphql.execution.executor", "graphql.execution.utils") def test_post_form_mutation_rollback(self): self.authenticate("admin", "admin") query = """ mutation { createPartner( name: "Le Héro, Toto", email: "toto@example.com", raiseAfterCreate: true ) { name } } """ data = {"query": query} r = self.url_open("/graphql/demo", data=data) self.assertEqual(r.status_code, 200) self.assertEqual(r.headers["Content-Type"], "application/json") self.assertIn("as requested", r.json()["errors"][0]["message"]) # a rollback must have occured self.assertEqual( len(self.env["res.partner"].search([("email", "=", "toto@example.com")])), 0 )