From 1ae76b9a22f15066a62852795ae7293c23b8693a Mon Sep 17 00:00:00 2001
From: Serghei Mihai <smihai@entrouvert.com>
Date: Tue, 11 Jun 2019 17:30:31 +0200
Subject: [PATCH] astregs: add initial connector (#33424)

---
 passerelle/apps/astregs/__init__.py           |   0
 .../apps/astregs/migrations/0001_initial.py   |  51 +++
 .../apps/astregs/migrations/__init__.py       |   0
 passerelle/apps/astregs/models.py             | 216 +++++++++++++
 passerelle/settings.py                        |   1 +
 tests/data/astregs/Contact.wsdl               | 267 ++++++++++++++++
 tests/data/astregs/Contact.xml                |   1 +
 tests/data/astregs/RechercheTiers.wsdl        | 135 ++++++++
 tests/data/astregs/RechercheTiers.xml         |   1 +
 tests/data/astregs/RechercheTiersDetails.wsdl | 156 +++++++++
 tests/data/astregs/RechercheTiersDetails.xml  |   1 +
 tests/data/astregs/RechercheTiersNoResult.xml |   1 +
 tests/data/astregs/Tiers.wsdl                 | 300 ++++++++++++++++++
 tests/data/astregs/Tiers.xml                  |   1 +
 tests/test_astregs.py                         | 120 +++++++
 15 files changed, 1251 insertions(+)
 create mode 100644 passerelle/apps/astregs/__init__.py
 create mode 100644 passerelle/apps/astregs/migrations/0001_initial.py
 create mode 100644 passerelle/apps/astregs/migrations/__init__.py
 create mode 100644 passerelle/apps/astregs/models.py
 create mode 100644 tests/data/astregs/Contact.wsdl
 create mode 100644 tests/data/astregs/Contact.xml
 create mode 100644 tests/data/astregs/RechercheTiers.wsdl
 create mode 100644 tests/data/astregs/RechercheTiers.xml
 create mode 100644 tests/data/astregs/RechercheTiersDetails.wsdl
 create mode 100644 tests/data/astregs/RechercheTiersDetails.xml
 create mode 100644 tests/data/astregs/RechercheTiersNoResult.xml
 create mode 100644 tests/data/astregs/Tiers.wsdl
 create mode 100644 tests/data/astregs/Tiers.xml
 create mode 100644 tests/test_astregs.py

diff --git a/passerelle/apps/astregs/__init__.py b/passerelle/apps/astregs/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/passerelle/apps/astregs/migrations/0001_initial.py b/passerelle/apps/astregs/migrations/0001_initial.py
new file mode 100644
index 00000000..d2130460
--- /dev/null
+++ b/passerelle/apps/astregs/migrations/0001_initial.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.20 on 2019-06-19 10:24
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('base', '0012_job'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='AstreGS',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('title', models.CharField(max_length=50, verbose_name='Title')),
+                ('description', models.TextField(verbose_name='Description')),
+                ('slug', models.SlugField(unique=True, verbose_name='Identifier')),
+                ('wsdl_base_url', models.URLField(verbose_name='Webservices base URL')),
+                ('username', models.CharField(max_length=32, verbose_name='Username')),
+                ('password', models.CharField(max_length=32, verbose_name='Password')),
+                ('organism', models.CharField(max_length=32, verbose_name='Organism')),
+                ('budget', models.CharField(max_length=32, verbose_name='Budget')),
+                ('exercice', models.CharField(max_length=32, verbose_name='Exercice')),
+                ('users', models.ManyToManyField(blank=True, related_name='_astregs_users_+', related_query_name='+', to='base.ApiUser')),
+            ],
+            options={
+                'verbose_name': 'AstresGS',
+            },
+        ),
+        migrations.CreateModel(
+            name='Link',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name_id', models.CharField(max_length=32)),
+                ('association_id', models.CharField(max_length=32)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='astregs.AstreGS')),
+            ],
+        ),
+        migrations.AlterUniqueTogether(
+            name='link',
+            unique_together=set([('resource', 'name_id', 'association_id')]),
+        ),
+    ]
diff --git a/passerelle/apps/astregs/migrations/__init__.py b/passerelle/apps/astregs/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/passerelle/apps/astregs/models.py b/passerelle/apps/astregs/models.py
new file mode 100644
index 00000000..e0491fc6
--- /dev/null
+++ b/passerelle/apps/astregs/models.py
@@ -0,0 +1,216 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2019  Entr'ouvert
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from zeep.helpers import serialize_object
+
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+from django.utils.six.moves.urllib import parse as urlparse
+from django.http import Http404
+
+from passerelle.base.models import BaseResource
+from passerelle.utils.api import endpoint
+
+LINK_CREATION_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-03/schema#',
+    'title': 'AstreGS Link',
+    'description': '',
+    'type': 'object',
+    'properties': {
+        'NameID': {
+            'description': 'user name_id',
+            'type': 'string',
+            'required': True
+        },
+        'association_id': {
+            'description': 'association id',
+            'type': 'string',
+            'required': True
+        }
+    }
+}
+
+
+class AstreGS(BaseResource):
+    wsdl_base_url = models.URLField(_('Webservices base URL'))
+    username = models.CharField(_('Username'), max_length=32)
+    password = models.CharField(_('Password'), max_length=32)
+    organism = models.CharField('Organisme', max_length=32)
+    budget = models.CharField('Budget', max_length=32)
+    exercice = models.CharField('Exercice', max_length=32)
+
+    category = _('Business Process Connectors')
+
+    class Meta:
+        verbose_name = u'AstresGS'
+
+    def check_status(self):
+        response = self.requests.get(self.wsdl_base_url)
+        response.raise_for_status()
+
+    @property
+    def authentication(self):
+        return {'USERNOM': self.username, 'USERPWD': self.password}
+
+    @property
+    def context(self):
+        return {'Organisme': self.organism,
+                'Budget': self.budget,
+                'Exercice': self.exercice}
+
+    def get_client(self, wsdl_name):
+        url = urlparse.urljoin(self.wsdl_base_url, '%s?wsdl' % wsdl_name)
+        client = self.soap_client(wsdl_url=url)
+        parsed_wsdl_address = urlparse.urlparse(client.service._binding_options['address'])
+        parsed_real_address = urlparse.urlparse(self.wsdl_base_url)
+        client.service._binding_options['address'] = urlparse.urlunparse(
+            parsed_real_address[:2] + parsed_wsdl_address[2:])
+        return client
+
+
+    @endpoint(description=_('Find associations by SIREN number'),
+              perm='can_access',
+              parameters={
+                  'siren': {'description': _('SIREN Number'),
+                            'example_value': '77567227216096'}
+                  }
+              )
+    def associations(self, request, siren):
+        client = self.get_client('RechercheTiersDetails')
+        r = client.service.liste(Authentification=self.authentication,
+                                 Contexte=self.context,
+                                 Criteres={'siren': '%s*' % siren})
+        data = []
+        if r.liste:
+            for item in r.liste.EnregRechercheTiersDetailsReturn:
+                association_data = serialize_object(item)
+                association_data['id'] = association_data['Numero_SIRET']
+                association_data['text'] = '%(Numero_SIRET)s - %(Nom_enregistrement)s' % association_data
+                association_data['code'] = association_data['Code_tiers']
+                association_data['name'] = association_data['Nom_enregistrement']
+                data.append(association_data)
+        return {'data': data}
+
+    @endpoint(description=_('Check if association exists by its SIRET number'),
+              name='check-association-by-siret',
+              perm='can_access',
+              parameters={
+                  'siret': {'description': _('SIRET Number'),
+                            'example_value': '7756722721609600014'}
+                  }
+              )
+    def check_association_by_siret(self, request, siret):
+        client = self.get_client('RechercheTiers')
+        r = client.service.liste(Authentification=self.authentication,
+                                 Contexte=self.context,
+                                 Criteres={'siren': siret})
+        if r.liste:
+            return {'exists': True}
+        return {'exists': False}
+
+    @endpoint(name='get-association-link-means',
+              description=_('Get association linking means'),
+              perm='can_access',
+              parameters={
+                  'association_id': {'description': _('Association ID'),
+                                     'example_value': '42435'}
+                  }
+    )
+    def get_association_link_means(self, request, association_id):
+        client = self.get_client('Tiers')
+        r = client.service.Chargement({'Authentification': self.authentication,
+                                       'Contexte': self.context,
+                                       'TiersCle': {'CodeTiers': association_id}})
+        data = []
+        # assocation contact is defined in EncodeKeyContact attribute
+        if not r.EncodeKeyContact:
+            return {'data': data}
+
+        client = self.get_client('Contact')
+        r = client.service.Chargement({'Authentification': self.authentication,
+                                       'Contexte': self.context,
+                                       'ContactCle': {'idContact': r.EncodeKeyContact}})
+        if r.AdresseMail:
+            data.append({'id': 'email',
+                         'text': 'par courriel vers %s***@***%s' % (r.AdresseMail[:2], r.AdresseMail[-3:]),
+                         'value': r.AdresseMail,
+                         'type': 'email'})
+        if r.TelephoneMobile:
+            data.append({'id': 'mobile',
+                         'text': 'par SMS vers %s****%s' % (r.TelephoneMobile[:2], r.TelephoneMobile[-3:]),
+                         'value': r.TelephoneMobile,
+                         'type': 'mobile'})
+        if r.RueVoie:
+            full_address = r.RueVoie
+            full_address += ', '
+            if r.CodePostal:
+                full_address += '%s ' % r.CodePostal
+            if r.Ville:
+                full_address += r.Ville
+            data.append({'id': 'address',
+                         'text': 'par courrier vers %s ***** %s' % (full_address[:10], full_address[-10:]),
+                         'address': r.RueVoie,
+                         'zicode': r.CodePostal,
+                         'city': r.Ville,
+                         'value': full_address,
+                         'type': 'mail'})
+        return {'data': data}
+
+    @endpoint(name='link', perm='can_access',
+              post={
+                  'description': _('Create link with an association'),
+                  'request_body': {
+                      'schema': {
+                          'application/json': LINK_CREATION_SCHEMA
+                      }
+                  }
+              }
+    )
+    def link(self, request, post_data):
+        link, created = Link.objects.get_or_create(resource=self, name_id=post_data['NameID'],
+                                                   association_id=post_data['association_id'])
+        return {'link': link.id, 'created': created, 'association_id': link.association_id}
+
+
+    @endpoint(description=_('Remove link to an association'),
+              perm='can_access',
+              parameters={
+                  'NameID':{
+                      'description': _('Publik NameID'),
+                      'example_value': 'xyz24d934',
+                  },
+                  'association_id':{
+                      'description': _('Association ID'),
+                      'example_value': '12345',
+                  }
+              })
+    def unlink(self, request, NameID, association_id):
+        try:
+            link = Link.objects.get(resource=self, name_id=NameID, association_id=association_id)
+            link.delete()
+            return {'deleted': True}
+        except Link.DoesNotExist:
+            raise Http404('link not found')
+
+
+class Link(models.Model):
+    resource = models.ForeignKey(AstreGS)
+    name_id = models.CharField(max_length=32)
+    association_id = models.CharField(max_length=32)
+    created = models.DateTimeField(auto_now_add=True)
+
+    class Meta:
+        unique_together = ('resource', 'name_id', 'association_id')
diff --git a/passerelle/settings.py b/passerelle/settings.py
index 2eaa5f29..d30235b6 100644
--- a/passerelle/settings.py
+++ b/passerelle/settings.py
@@ -122,6 +122,7 @@ INSTALLED_APPS = (
     'passerelle.apps.api_particulier',
     'passerelle.apps.arcgis',
     'passerelle.apps.arpege_ecp',
+    'passerelle.apps.astregs',
     'passerelle.apps.atal',
     'passerelle.apps.atos_genesys',
     'passerelle.apps.base_adresse',
diff --git a/tests/data/astregs/Contact.wsdl b/tests/data/astregs/Contact.wsdl
new file mode 100644
index 00000000..571d920b
--- /dev/null
+++ b/tests/data/astregs/Contact.wsdl
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions name="Contact" targetNamespace="http://gfi.astre.webservices/rf/gf/contact" xmlns:impl="http://gfi.astre.webservices/rf/gf/contact" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:intf="http://gfi.astre.webservices/rf/gf/contact">
+  <wsdl:types>
+    <schema elementFormDefault="qualified" targetNamespace="http://gfi.astre.webservices/rf/gf/contact" xmlns="http://www.w3.org/2001/XMLSchema">
+				<!--  request et response -->	
+			
+	<complexType name="Authentification">
+		<sequence>
+			<element name="USERNOM" type="string"/>
+			<element name="USERPWD" type="string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="Contexte">
+		<sequence>
+			<element name="Organisme" type="string"/>
+			<element name="Budget" type="string"/>
+			<element name="Exercice" type="string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="ContactRequest">
+				<sequence>
+			<element name="Authentification" type="impl:Authentification"/>
+			<element name="Contexte" type="impl:Contexte"/>
+		<element name="Contact" type="impl:Contact"/>
+				</sequence>
+			</complexType>
+		<complexType name="ContactResponse">
+			<sequence>		
+				<element name="ContactReturn" type="impl:Contact"/>
+			</sequence>
+		</complexType>
+		
+		<complexType name="Contact">
+		    <sequence>
+         <element name="idContact" nillable="true" type="xsd:string"/>
+         <element name="CodeContact" nillable="true" type="xsd:string"/>
+         <element name="CodeTitreCivilite" nillable="true" type="xsd:string"/>
+         <element name="Nom" nillable="true" type="xsd:string"/>
+         <element name="Prenom" nillable="true" type="xsd:string"/>
+         <element name="NomDeJeuneFille" nillable="true" type="xsd:string"/>
+         <element name="DateDeNaissance" nillable="true" type="xsd:string"/>
+         <element name="FormuleCivilite" nillable="true" type="xsd:string"/>
+         <element name="IntituleTitre2" nillable="true" type="xsd:string"/>
+         <element name="IntituleTitre3" nillable="true" type="xsd:string"/>
+         <element name="IntituleTitre4" nillable="true" type="xsd:string"/>
+         <element name="SituationDeFamille" nillable="true" type="xsd:string"/>
+         <element name="CodeFonction" nillable="true" type="xsd:string"/>
+         <element name="LibelleFonction" nillable="true" type="xsd:string"/>
+         <element name="TelephoneBureau" nillable="true" type="xsd:string"/>
+         <element name="TelephoneMobile" nillable="true" type="xsd:string"/>
+         <element name="NumeroDeFax" nillable="true" type="xsd:string"/>
+         <element name="AdresseMail" nillable="true" type="xsd:string"/>
+         <element name="PageWeb" nillable="true" type="xsd:string"/>
+         <element name="AdresseDestinataire" nillable="true" type="xsd:string"/>
+         <element name="AdresseComplementaire" nillable="true" type="xsd:string"/>
+         <element name="ComplementGeographique" nillable="true" type="xsd:string"/>
+         <element name="RueVoie" nillable="true" type="xsd:string"/>
+         <element name="ComplementVoie" nillable="true" type="xsd:string"/>
+         <element name="CodePostal" nillable="true" type="xsd:string"/>
+         <element name="Ville" nillable="true" type="xsd:string"/>
+         <element name="CodePays" nillable="true" type="xsd:string"/>
+         <element name="LibellePays" nillable="true" type="xsd:string"/>
+         <element name="LibelleAdresse" nillable="true" type="xsd:string"/>
+         <element name="Commentaire" nillable="true" type="xsd:string"/>
+</sequence>
+	</complexType>
+	
+	<complexType name="Contact_Cle">
+		<sequence>
+			<element name="idContact" nillable="true" type="xsd:string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="ContactRequest_Cles">
+	   	<sequence>
+			<element name="Authentification" type="impl:Authentification"/>
+			<element name="Contexte" type="impl:Contexte"/>
+		<element name="ContactCle" type="impl:Contact_Cle"/>
+		
+				</sequence>
+			</complexType>
+			
+		<element name="creation">
+			<complexType>
+				<sequence>
+					<element name="request" type="impl:ContactRequest"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="creationResponse">
+			<complexType>
+				<sequence>
+					<element name="response" type="impl:ContactResponse"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="modification">
+			<complexType>
+				<sequence>
+					<element name="request" type="impl:ContactRequest"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="modificationResponse">
+			<complexType>
+				<sequence>
+					<element name="response" type="impl:ContactResponse"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="suppression">
+			<complexType>
+				<sequence>
+					<element name="request" type="impl:ContactRequest_Cles"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="suppressionResponse">
+			<complexType>
+				<sequence>
+					<element name="response" type="impl:ContactResponse"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="chargement">
+			<complexType>
+				<sequence>
+					<element name="request" type="impl:ContactRequest_Cles"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="chargementResponse">
+			<complexType>
+				<sequence>
+					<element name="response" type="impl:ContactResponse"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		
+		</schema>
+  </wsdl:types>
+  <wsdl:message name="chargementRequest">
+    <wsdl:part name="request" element="impl:chargement">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="suppressionRequest">
+    <wsdl:part name="request" element="impl:suppression">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="modificationResponse">
+    <wsdl:part name="response" element="impl:modificationResponse">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="creationResponse">
+    <wsdl:part name="response" element="impl:creationResponse">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="chargementResponse">
+    <wsdl:part name="response" element="impl:chargementResponse">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="modificationRequest">
+    <wsdl:part name="request" element="impl:modification">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="suppressionResponse">
+    <wsdl:part name="response" element="impl:suppressionResponse">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="creationRequest">
+    <wsdl:part name="request" element="impl:creation">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:portType name="Contact">
+<wsdl:documentation>Web service des Contact Astre </wsdl:documentation>
+    <wsdl:operation name="Modification">
+<wsdl:documentation>
+				le champ encodeKey est obligatoire ainsi que le champ à modifier
+			</wsdl:documentation>
+      <wsdl:input name="modificationRequest" message="impl:modificationRequest">
+    </wsdl:input>
+      <wsdl:output name="modificationResponse" message="impl:modificationResponse">
+    </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Chargement">
+<wsdl:documentation>
+				le champ encodeKey est obligatoire
+			</wsdl:documentation>
+      <wsdl:input name="chargementRequest" message="impl:chargementRequest">
+    </wsdl:input>
+      <wsdl:output name="chargementResponse" message="impl:chargementResponse">
+    </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Creation">
+<wsdl:documentation>
+				tous les champs sont obligatoires
+			</wsdl:documentation>
+      <wsdl:input name="creationRequest" message="impl:creationRequest">
+    </wsdl:input>
+      <wsdl:output name="creationResponse" message="impl:creationResponse">
+    </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Suppression">
+<wsdl:documentation>
+				tous les champs sont obligatoires
+			</wsdl:documentation>
+      <wsdl:input name="suppressionRequest" message="impl:suppressionRequest">
+    </wsdl:input>
+      <wsdl:output name="suppressionResponse" message="impl:suppressionResponse">
+    </wsdl:output>
+    </wsdl:operation>
+  </wsdl:portType>
+  <wsdl:binding name="ContactSoapBinding" type="impl:Contact">
+    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <wsdl:operation name="Modification">
+      <wsdlsoap:operation soapAction=""/>
+      <wsdl:input name="modificationRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="modificationResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Suppression">
+      <wsdlsoap:operation soapAction=""/>
+      <wsdl:input name="suppressionRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="suppressionResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Creation">
+      <wsdlsoap:operation soapAction=""/>
+      <wsdl:input name="creationRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="creationResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Chargement">
+      <wsdlsoap:operation soapAction=""/>
+      <wsdl:input name="chargementRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="chargementResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+  </wsdl:binding>
+  <wsdl:service name="Contact">
+    <wsdl:port name="Contact" binding="impl:ContactSoapBinding">
+      <wsdlsoap:address location="http://10.1.20.153:28001/axis2/services/Contact/"/>
+    </wsdl:port>
+  </wsdl:service>
+</wsdl:definitions>
diff --git a/tests/data/astregs/Contact.xml b/tests/data/astregs/Contact.xml
new file mode 100644
index 00000000..fec6cf14
--- /dev/null
+++ b/tests/data/astregs/Contact.xml
@@ -0,0 +1 @@
+<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns1:chargementResponse xmlns:ns1="http://gfi.astre.webservices/rf/gf/contact"><ns1:response><ns1:ContactReturn><ns1:idContact>13012</ns1:idContact><ns1:CodeContact>AS173957</ns1:CodeContact><ns1:CodeTitreCivilite>035</ns1:CodeTitreCivilite><ns1:Nom>MARTIN</ns1:Nom><ns1:Prenom>Jean-Marc</ns1:Prenom><ns1:NomDeJeuneFille></ns1:NomDeJeuneFille><ns1:DateDeNaissance></ns1:DateDeNaissance><ns1:FormuleCivilite></ns1:FormuleCivilite><ns1:IntituleTitre2></ns1:IntituleTitre2><ns1:IntituleTitre3></ns1:IntituleTitre3><ns1:IntituleTitre4>Président de l&amp;#39;</ns1:IntituleTitre4><ns1:SituationDeFamille></ns1:SituationDeFamille><ns1:CodeFonction></ns1:CodeFonction><ns1:LibelleFonction></ns1:LibelleFonction><ns1:TelephoneBureau></ns1:TelephoneBureau><ns1:TelephoneMobile>0660909980</ns1:TelephoneMobile><ns1:NumeroDeFax></ns1:NumeroDeFax><ns1:AdresseMail>jeanmarcallan@neuf.fr</ns1:AdresseMail><ns1:PageWeb></ns1:PageWeb><ns1:AdresseDestinataire>Jean-Marc MARTIN</ns1:AdresseDestinataire><ns1:AdresseComplementaire></ns1:AdresseComplementaire><ns1:ComplementGeographique></ns1:ComplementGeographique><ns1:RueVoie>271 chemin de Curnier</ns1:RueVoie><ns1:ComplementVoie></ns1:ComplementVoie><ns1:CodePostal>06750</ns1:CodePostal><ns1:Ville>SERANON</ns1:Ville><ns1:CodePays>FR</ns1:CodePays><ns1:LibellePays>France</ns1:LibellePays><ns1:LibelleAdresse>SIEGE SOCIAL</ns1:LibelleAdresse><ns1:Commentaire></ns1:Commentaire></ns1:ContactReturn></ns1:response></ns1:chargementResponse></soapenv:Body></soapenv:Envelope>
diff --git a/tests/data/astregs/RechercheTiers.wsdl b/tests/data/astregs/RechercheTiers.wsdl
new file mode 100644
index 00000000..ebb681af
--- /dev/null
+++ b/tests/data/astregs/RechercheTiers.wsdl
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions name="RechercheTiers" targetNamespace="http://gfi.astre.webservices/gf/recherchetiers" xmlns:impl="http://gfi.astre.webservices/gf/recherchetiers" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
+  <wsdl:types>
+    <schema elementFormDefault="qualified" targetNamespace="http://gfi.astre.webservices/gf/recherchetiers" xmlns="http://www.w3.org/2001/XMLSchema">
+	  
+	
+	<complexType name="Authentification">
+		<sequence>
+			<element name="USERNOM" type="string"/>
+			<element name="USERPWD" type="string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="Contexte">
+		<sequence>
+			<element name="Organisme" type="string"/>
+			<element name="Budget" type="string"/>
+			<element name="Exercice" type="string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="CriteresRequest">
+		<sequence>
+			<element name="Authentification" type="impl:Authentification"/>
+			<element name="Contexte" type="impl:Contexte"/>
+			<element name="Criteres" type="impl:RechercheTiers"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="ListeRechercheTiers">
+			<sequence>
+				<element maxOccurs="unbounded" minOccurs="0" name="EnregRechercheTiersReturn" type="impl:EnregRechercheTiers"/>
+		</sequence>
+	</complexType>
+	
+	 
+	<complexType name="RechercheResponse">
+		<sequence>
+			<element name="criteres" type="impl:RechercheTiers"/>
+			<element name="liste" type="impl:ListeRechercheTiers"/>
+		</sequence>
+	</complexType>			
+
+	<complexType name="RechercheTiers">
+		<sequence>
+	
+			<element name="NbEnreg" nillable="true" type="xsd:string"/>
+			<element name="ListeResultat" nillable="true" type="xsd:string"/>
+			<element name="casseCodeTiers" nillable="true" type="xsd:string"/>
+			<element name="NbEnregPage" nillable="true" type="xsd:string"/>
+			<element name="isFinancier" nillable="true" type="xsd:string"/>
+			<element name="numeroTiers" nillable="true" type="xsd:string"/>
+			<element name="nom" nillable="true" type="xsd:string"/>
+			<element name="nomSigleRaison" nillable="true" type="xsd:string"/>
+			<element name="nomContact" nillable="true" type="xsd:string"/>
+			<element name="indicateurAssociation" nillable="true" type="xsd:string"/>
+			<element name="codeFamille" nillable="true" type="xsd:string"/>
+			<element name="libelleFamille" nillable="true" type="xsd:string"/>
+			<element name="siren" nillable="true" type="xsd:string"/>
+			<element name="agence" nillable="true" type="xsd:string"/>
+			<element name="codeApe" nillable="true" type="xsd:string"/>
+			<element name="libelleCodeApe" nillable="true" type="xsd:string"/>
+			<element name="banque" nillable="true" type="xsd:string"/>
+			<element name="guichet" nillable="true" type="xsd:string"/>
+			<element name="numeroCompte" nillable="true" type="xsd:string"/>
+			<element name="cleRIB" nillable="true" type="xsd:string"/>
+			<element name="AdrEmail" nillable="true" type="xsd:string"/>
+			<element name="codePostal" nillable="true" type="xsd:string"/>
+			<element name="ville" nillable="true" type="xsd:string"/>
+			<element name="encodeKeyStatut" nillable="true" type="xsd:string"/>
+			<element name="typeTiers" nillable="true" type="xsd:string"/>
+			<element name="isPermanent" nillable="true" type="xsd:string"/>
+			<element name="ancienNumero" nillable="true" type="xsd:string"/>
+			<element name="encodeKeyNomana" nillable="true" type="xsd:string"/>
+			<element name="codeElement" nillable="true" type="xsd:string"/>
+			<element name="codeService" nillable="true" type="xsd:string"/>
+			<element name="encodeKeyIdCompl" nillable="true" type="xsd:string"/>
+			<element name="valeurIdCompl" nillable="true" type="xsd:string"/>
+
+			</sequence>
+		</complexType>
+
+	 <element name="request" type="impl:CriteresRequest"/>
+	 <element name="response" type="impl:RechercheResponse"/>	
+
+	<complexType name="EnregRechercheTiers">
+			<all>
+		
+			<element name="T_0TIERS_ID" nillable="true" type="xsd:string"/>	
+			<element name="N" nillable="true" type="xsd:string"/>	
+			<element name="Nom_Enregistrement" nillable="true" type="xsd:string"/>	
+			<element name="Sigle" nillable="true" type="xsd:string"/>	
+			<element name="Raison_Sociale" nillable="true" type="xsd:string"/>	
+			<element name="Raison_Sociale_2" nillable="true" type="xsd:string"/>	
+			<element name="Code_Postal" nillable="true" type="xsd:string"/>	
+			<element name="Localite" nillable="true" type="xsd:string"/>
+			</all>
+		</complexType>
+	</schema>
+  </wsdl:types>
+  <wsdl:message name="CriteresRequest">
+    <wsdl:part name="request" element="impl:request">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="ListeResponse">
+    <wsdl:part name="response" element="impl:response">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:portType name="RechercheTiers">
+<wsdl:documentation>Web Service RechercheTiers Astre</wsdl:documentation>
+    <wsdl:operation name="liste">
+      <wsdl:input name="CriteresRequest" message="impl:CriteresRequest">
+    </wsdl:input>
+      <wsdl:output name="ListeResponse" message="impl:ListeResponse">
+    </wsdl:output>
+    </wsdl:operation>
+  </wsdl:portType>
+  <wsdl:binding name="RechercheTiersSoapBinding" type="impl:RechercheTiers">
+    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <wsdl:operation name="liste">
+      <wsdlsoap:operation soapAction="http://gfi.astre.webservices/gf/RechercheTiers/Chargement"/>
+      <wsdl:input name="CriteresRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="ListeResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+  </wsdl:binding>
+  <wsdl:service name="RechercheTiers">
+    <wsdl:port name="RechercheTiers" binding="impl:RechercheTiersSoapBinding">
+      <wsdlsoap:address location="http://10.1.20.153:28001/axis2/services/RechercheTiers/"/>
+    </wsdl:port>
+  </wsdl:service>
+</wsdl:definitions>
diff --git a/tests/data/astregs/RechercheTiers.xml b/tests/data/astregs/RechercheTiers.xml
new file mode 100644
index 00000000..54e983b5
--- /dev/null
+++ b/tests/data/astregs/RechercheTiers.xml
@@ -0,0 +1 @@
+<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns1:response xmlns:ns1="http://gfi.astre.webservices/gf/recherchetiers"><ns1:criteres><ns1:NbEnreg>1</ns1:NbEnreg><ns1:ListeResultat></ns1:ListeResultat><ns1:casseCodeTiers>false</ns1:casseCodeTiers><ns1:NbEnregPage>15</ns1:NbEnregPage><ns1:isFinancier></ns1:isFinancier><ns1:numeroTiers></ns1:numeroTiers><ns1:nom></ns1:nom><ns1:nomSigleRaison></ns1:nomSigleRaison><ns1:nomContact></ns1:nomContact><ns1:indicateurAssociation></ns1:indicateurAssociation><ns1:codeFamille></ns1:codeFamille><ns1:libelleFamille></ns1:libelleFamille><ns1:siren>44999696600015</ns1:siren><ns1:agence></ns1:agence><ns1:codeApe></ns1:codeApe><ns1:libelleCodeApe></ns1:libelleCodeApe><ns1:banque></ns1:banque><ns1:guichet></ns1:guichet><ns1:numeroCompte></ns1:numeroCompte><ns1:cleRIB></ns1:cleRIB><ns1:AdrEmail></ns1:AdrEmail><ns1:codePostal></ns1:codePostal><ns1:ville></ns1:ville><ns1:encodeKeyStatut>||</ns1:encodeKeyStatut><ns1:typeTiers></ns1:typeTiers><ns1:isPermanent></ns1:isPermanent><ns1:ancienNumero></ns1:ancienNumero><ns1:encodeKeyNomana></ns1:encodeKeyNomana><ns1:codeElement></ns1:codeElement><ns1:codeService></ns1:codeService><ns1:encodeKeyIdCompl></ns1:encodeKeyIdCompl><ns1:valeurIdCompl></ns1:valeurIdCompl></ns1:criteres><ns1:liste><ns1:EnregRechercheTiersReturn><ns1:T_0TIERS_ID>|253593|</ns1:T_0TIERS_ID><ns1:N>364163</ns1:N><ns1:Nom_Enregistrement>ALLIANCE JUDO 06</ns1:Nom_Enregistrement><ns1:Sigle></ns1:Sigle><ns1:Raison_Sociale>ALLIANCE JUDO 06</ns1:Raison_Sociale><ns1:Raison_Sociale_2></ns1:Raison_Sociale_2><ns1:Code_Postal>06220</ns1:Code_Postal><ns1:Localite>VALLAURIS</ns1:Localite></ns1:EnregRechercheTiersReturn></ns1:liste></ns1:response></soapenv:Body></soapenv:Envelope>
diff --git a/tests/data/astregs/RechercheTiersDetails.wsdl b/tests/data/astregs/RechercheTiersDetails.wsdl
new file mode 100644
index 00000000..fa9324dc
--- /dev/null
+++ b/tests/data/astregs/RechercheTiersDetails.wsdl
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions name="RechercheTiersDetails" targetNamespace="http://gfi.astre.webservices/gf/recherchetiersdetails" xmlns:impl="http://gfi.astre.webservices/gf/recherchetiersdetails" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
+  <wsdl:types>
+    <schema elementFormDefault="qualified" targetNamespace="http://gfi.astre.webservices/gf/recherchetiersdetails" xmlns="http://www.w3.org/2001/XMLSchema">
+	  
+	
+	<complexType name="Authentification">
+		<sequence>
+			<element name="USERNOM" type="string"/>
+			<element name="USERPWD" type="string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="Contexte">
+		<sequence>
+			<element name="Organisme" type="string"/>
+			<element name="Budget" type="string"/>
+			<element name="Exercice" type="string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="CriteresRequest">
+		<sequence>
+			<element name="Authentification" type="impl:Authentification"/>
+			<element name="Contexte" type="impl:Contexte"/>
+			<element name="Criteres" type="impl:RechercheTiersDetails"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="ListeRechercheTiersDetails">
+			<sequence>
+				<element maxOccurs="unbounded" minOccurs="0" name="EnregRechercheTiersDetailsReturn" type="impl:EnregRechercheTiersDetails"/>
+		</sequence>
+	</complexType>
+	
+	 
+	<complexType name="RechercheResponse">
+		<sequence>
+			<element name="criteres" type="impl:RechercheTiersDetails"/>
+			<element name="liste" type="impl:ListeRechercheTiersDetails"/>
+		</sequence>
+	</complexType>			
+
+	<complexType name="RechercheTiersDetails">
+		<sequence>
+	
+			<element name="NbEnreg" nillable="true" type="xsd:string"/>
+			<element name="ListeResultat" nillable="true" type="xsd:string"/>
+			<element name="casseCodeTiers" nillable="true" type="xsd:string"/>
+			<element name="NbEnregPage" nillable="true" type="xsd:string"/>
+			<element name="isFinancier" nillable="true" type="xsd:string"/>
+			<element name="numeroTiers" nillable="true" type="xsd:string"/>
+			<element name="nom" nillable="true" type="xsd:string"/>
+			<element name="nomSigleRaison" nillable="true" type="xsd:string"/>
+			<element name="nomContact" nillable="true" type="xsd:string"/>
+			<element name="indicateurAssociation" nillable="true" type="xsd:string"/>
+			<element name="codeFamille" nillable="true" type="xsd:string"/>
+			<element name="libelleFamille" nillable="true" type="xsd:string"/>
+			<element name="siren" nillable="true" type="xsd:string"/>
+			<element name="agence" nillable="true" type="xsd:string"/>
+			<element name="codeApe" nillable="true" type="xsd:string"/>
+			<element name="libelleCodeApe" nillable="true" type="xsd:string"/>
+			<element name="banque" nillable="true" type="xsd:string"/>
+			<element name="guichet" nillable="true" type="xsd:string"/>
+			<element name="numeroCompte" nillable="true" type="xsd:string"/>
+			<element name="cleRIB" nillable="true" type="xsd:string"/>
+			<element name="AdrEmail" nillable="true" type="xsd:string"/>
+			<element name="codePostal" nillable="true" type="xsd:string"/>
+			<element name="ville" nillable="true" type="xsd:string"/>
+			<element name="encodeKeyStatut" nillable="true" type="xsd:string"/>
+			<element name="typeTiers" nillable="true" type="xsd:string"/>
+			<element name="isPermanent" nillable="true" type="xsd:string"/>
+			<element name="ancienNumero" nillable="true" type="xsd:string"/>
+			<element name="encodeKeyNomana" nillable="true" type="xsd:string"/>
+			<element name="codeElement" nillable="true" type="xsd:string"/>
+			<element name="codeService" nillable="true" type="xsd:string"/>
+			<element name="encodeKeyIdCompl" nillable="true" type="xsd:string"/>
+			<element name="valeurIdCompl" nillable="true" type="xsd:string"/>
+
+			</sequence>
+		</complexType>
+
+	 <element name="request" type="impl:CriteresRequest"/>
+	 <element name="response" type="impl:RechercheResponse"/>	
+
+	<complexType name="EnregRechercheTiersDetails">
+			<all>
+		
+			<element name="TIERS_ID" nillable="true" type="xsd:string"/>	
+			<element name="Code_tiers" nillable="true" type="xsd:string"/>	
+			<element name="Organisme" nillable="true" type="xsd:string"/>	
+			<element name="Nom_enregistrement" nillable="true" type="xsd:string"/>	
+			<element name="Code_postal" nillable="true" type="xsd:string"/>	
+			<element name="Libelle_Postale" nillable="true" type="xsd:string"/>	
+			<element name="Adresse_destinataire" nillable="true" type="xsd:string"/>	
+			<element name="Telephone" nillable="true" type="xsd:string"/>	
+			<element name="Indicateur_tiers_financier" nillable="true" type="xsd:string"/>	
+			<element name="Code_Famille_du_tiers" nillable="true" type="xsd:string"/>	
+			<element name="libelle_court_de_la_famille" nillable="true" type="xsd:string"/>	
+			<element name="Adresse_complementaire" nillable="true" type="xsd:string"/>	
+			<element name="Numero_de_Fax" nillable="true" type="xsd:string"/>	
+			<element name="le_libelle_court_du_statut" nillable="true" type="xsd:string"/>	
+			<element name="Sigle" nillable="true" type="xsd:string"/>	
+			<element name="Complement_geographique" nillable="true" type="xsd:string"/>	
+			<element name="adresse_email" nillable="true" type="xsd:string"/>	
+			<element name="Type_Tiers_D_ou_Fournisseur_ou_" nillable="true" type="xsd:string"/>	
+			<element name="Nature_juridique_du_debiteur" nillable="true" type="xsd:string"/>	
+			<element name="libelle_court" nillable="true" type="xsd:string"/>	
+			<element name="Rue_-_Voie" nillable="true" type="xsd:string"/>	
+			<element name="Page_Web" nillable="true" type="xsd:string"/>	
+			<element name="Indicateur_tiers_permanent" nillable="true" type="xsd:string"/>	
+			<element name="Code_APE_tiers" nillable="true" type="xsd:string"/>	
+			<element name="Libelle_court" nillable="true" type="xsd:string"/>	
+			<element name="Complement_voie_-_lieu_dit_-_BP" nillable="true" type="xsd:string"/>	
+			<element name="identifiant_de_tiers_de_reprise" nillable="true" type="xsd:string"/>	
+			<element name="Tiers_a_declarer_aux__fiscaux" nillable="true" type="xsd:string"/>	
+			<element name="Numero_SIRET" nillable="true" type="xsd:string"/>
+			</all>
+		</complexType>
+	</schema>
+  </wsdl:types>
+  <wsdl:message name="CriteresRequest">
+    <wsdl:part name="request" element="impl:request">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="ListeResponse">
+    <wsdl:part name="response" element="impl:response">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:portType name="RechercheTiersDetails">
+<wsdl:documentation>Web Service RechercheTiersDetails Astre</wsdl:documentation>
+    <wsdl:operation name="liste">
+      <wsdl:input name="CriteresRequest" message="impl:CriteresRequest">
+    </wsdl:input>
+      <wsdl:output name="ListeResponse" message="impl:ListeResponse">
+    </wsdl:output>
+    </wsdl:operation>
+  </wsdl:portType>
+  <wsdl:binding name="RechercheTiersDetailsSoapBinding" type="impl:RechercheTiersDetails">
+    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <wsdl:operation name="liste">
+      <wsdlsoap:operation soapAction="http://gfi.astre.webservices/gf/RechercheTiersDetails/Chargement"/>
+      <wsdl:input name="CriteresRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="ListeResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+  </wsdl:binding>
+  <wsdl:service name="RechercheTiersDetails">
+    <wsdl:port name="RechercheTiersDetails" binding="impl:RechercheTiersDetailsSoapBinding">
+      <wsdlsoap:address location="http://10.1.20.153:28001/axis2/services/RechercheTiersDetails/"/>
+    </wsdl:port>
+  </wsdl:service>
+</wsdl:definitions>
diff --git a/tests/data/astregs/RechercheTiersDetails.xml b/tests/data/astregs/RechercheTiersDetails.xml
new file mode 100644
index 00000000..c573d811
--- /dev/null
+++ b/tests/data/astregs/RechercheTiersDetails.xml
@@ -0,0 +1 @@
+<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns1:response xmlns:ns1="http://gfi.astre.webservices/gf/recherchetiersdetails"><ns1:criteres><ns1:NbEnreg>1</ns1:NbEnreg><ns1:ListeResultat></ns1:ListeResultat><ns1:casseCodeTiers>false</ns1:casseCodeTiers><ns1:NbEnregPage>15</ns1:NbEnregPage><ns1:isFinancier></ns1:isFinancier><ns1:numeroTiers></ns1:numeroTiers><ns1:nom></ns1:nom><ns1:nomSigleRaison></ns1:nomSigleRaison><ns1:nomContact></ns1:nomContact><ns1:indicateurAssociation></ns1:indicateurAssociation><ns1:codeFamille></ns1:codeFamille><ns1:libelleFamille></ns1:libelleFamille><ns1:siren>500433909*</ns1:siren><ns1:agence></ns1:agence><ns1:codeApe></ns1:codeApe><ns1:libelleCodeApe></ns1:libelleCodeApe><ns1:banque></ns1:banque><ns1:guichet></ns1:guichet><ns1:numeroCompte></ns1:numeroCompte><ns1:cleRIB></ns1:cleRIB><ns1:AdrEmail></ns1:AdrEmail><ns1:codePostal></ns1:codePostal><ns1:ville></ns1:ville><ns1:encodeKeyStatut>||</ns1:encodeKeyStatut><ns1:typeTiers></ns1:typeTiers><ns1:isPermanent></ns1:isPermanent><ns1:ancienNumero></ns1:ancienNumero><ns1:encodeKeyNomana></ns1:encodeKeyNomana><ns1:codeElement></ns1:codeElement><ns1:codeService></ns1:codeService><ns1:encodeKeyIdCompl></ns1:encodeKeyIdCompl><ns1:valeurIdCompl></ns1:valeurIdCompl></ns1:criteres><ns1:liste><ns1:EnregRechercheTiersDetailsReturn><ns1:TIERS_ID>11975</ns1:TIERS_ID><ns1:Code_tiers>173957</ns1:Code_tiers><ns1:Organisme>CG06</ns1:Organisme><ns1:Nom_enregistrement>ASSOCIATION OMNISPORTS DES MONTS D AZUR</ns1:Nom_enregistrement><ns1:Code_postal>06750</ns1:Code_postal><ns1:Libelle_Postale>SERANON</ns1:Libelle_Postale><ns1:Adresse_destinataire>ASS OMNISPORTS DES MONTS D AZUR</ns1:Adresse_destinataire><ns1:Telephone></ns1:Telephone><ns1:Indicateur_tiers_financier>1</ns1:Indicateur_tiers_financier><ns1:Code_Famille_du_tiers>51</ns1:Code_Famille_du_tiers><ns1:libelle_court_de_la_famille>PES-ASSOCIATIONS</ns1:libelle_court_de_la_famille><ns1:Adresse_complementaire></ns1:Adresse_complementaire><ns1:Numero_de_Fax></ns1:Numero_de_Fax><ns1:le_libelle_court_du_statut>validé</ns1:le_libelle_court_du_statut><ns1:Sigle></ns1:Sigle><ns1:Complement_geographique></ns1:Complement_geographique><ns1:adresse_email></ns1:adresse_email><ns1:Type_Tiers_D_ou_Fournisseur_ou_>*</ns1:Type_Tiers_D_ou_Fournisseur_ou_><ns1:Nature_juridique_du_debiteur>F1</ns1:Nature_juridique_du_debiteur><ns1:libelle_court></ns1:libelle_court><ns1:Rue_-_Voie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="1" /><ns1:Page_Web></ns1:Page_Web><ns1:Indicateur_tiers_permanent>1</ns1:Indicateur_tiers_permanent><ns1:Code_APE_tiers></ns1:Code_APE_tiers><ns1:Libelle_court xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="1" /><ns1:Complement_voie_-_lieu_dit_-_BP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="1" /><ns1:identifiant_de_tiers_de_reprise>173957</ns1:identifiant_de_tiers_de_reprise><ns1:Tiers_a_declarer_aux__fiscaux>0</ns1:Tiers_a_declarer_aux__fiscaux><ns1:Numero_SIRET>50043390900016</ns1:Numero_SIRET></ns1:EnregRechercheTiersDetailsReturn></ns1:liste></ns1:response></soapenv:Body></soapenv:Envelope>
diff --git a/tests/data/astregs/RechercheTiersNoResult.xml b/tests/data/astregs/RechercheTiersNoResult.xml
new file mode 100644
index 00000000..d139f78a
--- /dev/null
+++ b/tests/data/astregs/RechercheTiersNoResult.xml
@@ -0,0 +1 @@
+<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns1:response xmlns:ns1="http://gfi.astre.webservices/gf/recherchetiers"><ns1:criteres><ns1:NbEnreg>0</ns1:NbEnreg><ns1:ListeResultat></ns1:ListeResultat><ns1:casseCodeTiers>false</ns1:casseCodeTiers><ns1:NbEnregPage>15</ns1:NbEnregPage><ns1:isFinancier></ns1:isFinancier><ns1:numeroTiers></ns1:numeroTiers><ns1:nom></ns1:nom><ns1:nomSigleRaison></ns1:nomSigleRaison><ns1:nomContact></ns1:nomContact><ns1:indicateurAssociation></ns1:indicateurAssociation><ns1:codeFamille></ns1:codeFamille><ns1:libelleFamille></ns1:libelleFamille><ns1:siren>449996966000</ns1:siren><ns1:agence></ns1:agence><ns1:codeApe></ns1:codeApe><ns1:libelleCodeApe></ns1:libelleCodeApe><ns1:banque></ns1:banque><ns1:guichet></ns1:guichet><ns1:numeroCompte></ns1:numeroCompte><ns1:cleRIB></ns1:cleRIB><ns1:AdrEmail></ns1:AdrEmail><ns1:codePostal></ns1:codePostal><ns1:ville></ns1:ville><ns1:encodeKeyStatut>||</ns1:encodeKeyStatut><ns1:typeTiers></ns1:typeTiers><ns1:isPermanent></ns1:isPermanent><ns1:ancienNumero></ns1:ancienNumero><ns1:encodeKeyNomana></ns1:encodeKeyNomana><ns1:codeElement></ns1:codeElement><ns1:codeService></ns1:codeService><ns1:encodeKeyIdCompl></ns1:encodeKeyIdCompl><ns1:valeurIdCompl></ns1:valeurIdCompl></ns1:criteres><ns1:liste /></ns1:response></soapenv:Body></soapenv:Envelope>
diff --git a/tests/data/astregs/Tiers.wsdl b/tests/data/astregs/Tiers.wsdl
new file mode 100644
index 00000000..f352e9f8
--- /dev/null
+++ b/tests/data/astregs/Tiers.wsdl
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions name="Tiers" targetNamespace="http://gfi.astre.webservices/gf/tiers" xmlns:impl="http://gfi.astre.webservices/gf/tiers" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:intf="http://gfi.astre.webservices/gf/tiers">
+  <wsdl:types>
+    <schema elementFormDefault="qualified" targetNamespace="http://gfi.astre.webservices/gf/tiers" xmlns="http://www.w3.org/2001/XMLSchema">
+				<!--  request et response -->	
+			
+	<complexType name="Authentification">
+		<sequence>
+			<element name="USERNOM" type="string"/>
+			<element name="USERPWD" type="string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="Contexte">
+		<sequence>
+			<element name="Organisme" type="string"/>
+			<element name="Budget" type="string"/>
+			<element name="Exercice" type="string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="TiersRequest">
+				<sequence>
+			<element name="Authentification" type="impl:Authentification"/>
+			<element name="Contexte" type="impl:Contexte"/>
+		<element name="Tiers" type="impl:Tiers"/>
+				</sequence>
+			</complexType>
+		<complexType name="TiersResponse">
+			<sequence>		
+				<element name="TiersReturn" type="impl:Tiers"/>
+			</sequence>
+		</complexType>
+		
+		<complexType name="Tiers">
+		    <sequence>
+         <element name="Financier" nillable="true" type="xsd:string"/>
+         <element name="CodeTiers" nillable="true" type="xsd:string"/>
+         <element name="CodeFamille" nillable="true" type="xsd:string"/>
+         <element name="CatTiers" nillable="true" type="xsd:string"/>
+         <element name="CodeCivilite" nillable="true" type="xsd:string"/>
+         <element name="NomEnregistrement" nillable="true" type="xsd:string"/>
+         <element name="Nom" nillable="true" type="xsd:string"/>
+         <element name="Prenom" nillable="true" type="xsd:string"/>
+         <element name="Sigle" nillable="true" type="xsd:string"/>
+         <element name="Organisme" nillable="true" type="xsd:string"/>
+         <element name="RaisonSociale3" nillable="true" type="xsd:string"/>
+         <element name="RaisonSociale4" nillable="true" type="xsd:string"/>
+         <element name="RaisonSociale5" nillable="true" type="xsd:string"/>
+         <element name="RaisonSociale6" nillable="true" type="xsd:string"/>
+         <element name="LibelleCourrier" nillable="true" type="xsd:string"/>
+         <element name="EncodeKeyNatjur" nillable="true" type="xsd:string"/>
+         <element name="CodeAPE" nillable="true" type="xsd:string"/>
+         <element name="NumeroSiret" nillable="true" type="xsd:string"/>
+         <element name="NumeroSiretFin" nillable="true" type="xsd:string"/>
+         <element name="Commentaire" nillable="true" type="xsd:string"/>
+         <element name="AdresseDestinataire" nillable="true" type="xsd:string"/>
+         <element name="AdresseTitre" nillable="true" type="xsd:string"/>
+         <element name="IdentifiantAdresse" nillable="true" type="xsd:string"/>
+         <element name="AdresseIsAdresseDeFacturation" nillable="true" type="xsd:string"/>
+         <element name="AdresseIsAdresseDeCommande" nillable="true" type="xsd:string"/>
+         <element name="AdresseComplementDestinataire" nillable="true" type="xsd:string"/>
+         <element name="AdresseComplementaire" nillable="true" type="xsd:string"/>
+         <element name="AdresseLibelleRue" nillable="true" type="xsd:string"/>
+         <element name="AdresseComplementVoie" nillable="true" type="xsd:string"/>
+         <element name="AdresseCodePostal" nillable="true" type="xsd:string"/>
+         <element name="AdresseBureauDistributeur" nillable="true" type="xsd:string"/>
+         <element name="AdresseCodePays" nillable="true" type="xsd:string"/>
+         <element name="AdresseLibellePays" nillable="true" type="xsd:string"/>
+         <element name="NumeroTelephone" nillable="true" type="xsd:string"/>
+         <element name="NumeroFax" nillable="true" type="xsd:string"/>
+         <element name="Mail" nillable="true" type="xsd:string"/>
+         <element name="SiteWeb" nillable="true" type="xsd:string"/>
+         <element name="CodeTiersReprise" nillable="true" type="xsd:string"/>
+         <element name="StatutTiers" nillable="true" type="xsd:string"/>
+         <element name="Type" nillable="true" type="xsd:string"/>
+         <element name="Permanent" nillable="true" type="xsd:string"/>
+         <element name="IndSeuil" nillable="true" type="xsd:string"/>
+         <element name="DelaiSuiviFacture" nillable="true" type="xsd:string"/>
+         <element name="Remise" nillable="true" type="xsd:string"/>
+         <element name="DeclarationFiscale" nillable="true" type="xsd:string"/>
+         <element name="IndicateurTiersSubrogatoire" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant0" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant1" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant2" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant3" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant4" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant5" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant6" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant7" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant8" nillable="true" type="xsd:string"/>
+         <element name="ValeurIdentifiant9" nillable="true" type="xsd:string"/>
+         <element name="NoDeclarationPref" nillable="true" type="xsd:string"/>
+         <element name="TiersContactId" nillable="true" type="xsd:string"/>
+         <element name="EncodeKeyContact" nillable="true" type="xsd:string"/>
+         <element name="EncodeKeyFonction" nillable="true" type="xsd:string"/>
+         <element name="LibelleFonction" nillable="true" type="xsd:string"/>
+         <element name="DateDebutFonction" nillable="true" type="xsd:string"/> 
+         <element name="DateFinFonction" nillable="true" type="xsd:string"/>
+</sequence>
+	</complexType>
+	
+	<complexType name="Tiers_Cle">
+		<sequence>
+			<element name="CodeTiers" nillable="true" type="xsd:string"/>
+		</sequence>
+	</complexType>
+	
+	<complexType name="TiersRequest_Cles">
+	   	<sequence>
+			<element name="Authentification" type="impl:Authentification"/>
+			<element name="Contexte" type="impl:Contexte"/>
+		<element name="TiersCle" type="impl:Tiers_Cle"/>
+		
+				</sequence>
+			</complexType>
+			
+		<element name="creation">
+			<complexType>
+				<sequence>
+					<element name="request" type="impl:TiersRequest"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="creationResponse">
+			<complexType>
+				<sequence>
+					<element name="response" type="impl:TiersResponse"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="modification">
+			<complexType>
+				<sequence>
+					<element name="request" type="impl:TiersRequest"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="modificationResponse">
+			<complexType>
+				<sequence>
+					<element name="response" type="impl:TiersResponse"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="suppression">
+			<complexType>
+				<sequence>
+					<element name="request" type="impl:TiersRequest_Cles"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="suppressionResponse">
+			<complexType>
+				<sequence>
+					<element name="response" type="impl:TiersResponse"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="chargement">
+			<complexType>
+				<sequence>
+					<element name="request" type="impl:TiersRequest_Cles"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		<element name="chargementResponse">
+			<complexType>
+				<sequence>
+					<element name="response" type="impl:TiersResponse"/>
+				</sequence>
+			</complexType>
+		</element>
+		
+		
+		</schema>
+  </wsdl:types>
+  <wsdl:message name="modificationResponse">
+    <wsdl:part name="response" element="impl:modificationResponse">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="suppressionRequest">
+    <wsdl:part name="request" element="impl:suppression">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="chargementRequest">
+    <wsdl:part name="request" element="impl:chargement">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="suppressionResponse">
+    <wsdl:part name="response" element="impl:suppressionResponse">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="creationRequest">
+    <wsdl:part name="request" element="impl:creation">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="modificationRequest">
+    <wsdl:part name="request" element="impl:modification">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="creationResponse">
+    <wsdl:part name="response" element="impl:creationResponse">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:message name="chargementResponse">
+    <wsdl:part name="response" element="impl:chargementResponse">
+    </wsdl:part>
+  </wsdl:message>
+  <wsdl:portType name="Tiers">
+<wsdl:documentation>Web service des Tiers Astre </wsdl:documentation>
+    <wsdl:operation name="Modification">
+<wsdl:documentation>
+				le champ encodeKey est obligatoire ainsi que le champ à modifier
+			</wsdl:documentation>
+      <wsdl:input name="modificationRequest" message="impl:modificationRequest">
+    </wsdl:input>
+      <wsdl:output name="modificationResponse" message="impl:modificationResponse">
+    </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Chargement">
+<wsdl:documentation>
+				le champ encodeKey est obligatoire
+			</wsdl:documentation>
+      <wsdl:input name="chargementRequest" message="impl:chargementRequest">
+    </wsdl:input>
+      <wsdl:output name="chargementResponse" message="impl:chargementResponse">
+    </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Creation">
+<wsdl:documentation>
+				tous les champs sont obligatoires
+			</wsdl:documentation>
+      <wsdl:input name="creationRequest" message="impl:creationRequest">
+    </wsdl:input>
+      <wsdl:output name="creationResponse" message="impl:creationResponse">
+    </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Suppression">
+<wsdl:documentation>
+				tous les champs sont obligatoires
+			</wsdl:documentation>
+      <wsdl:input name="suppressionRequest" message="impl:suppressionRequest">
+    </wsdl:input>
+      <wsdl:output name="suppressionResponse" message="impl:suppressionResponse">
+    </wsdl:output>
+    </wsdl:operation>
+  </wsdl:portType>
+  <wsdl:binding name="TiersSoapBinding" type="impl:Tiers">
+    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <wsdl:operation name="Modification">
+      <wsdlsoap:operation soapAction=""/>
+      <wsdl:input name="modificationRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="modificationResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Suppression">
+      <wsdlsoap:operation soapAction=""/>
+      <wsdl:input name="suppressionRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="suppressionResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Creation">
+      <wsdlsoap:operation soapAction=""/>
+      <wsdl:input name="creationRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="creationResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="Chargement">
+      <wsdlsoap:operation soapAction=""/>
+      <wsdl:input name="chargementRequest">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="chargementResponse">
+        <wsdlsoap:body use="literal"/>
+      </wsdl:output>
+    </wsdl:operation>
+  </wsdl:binding>
+  <wsdl:service name="Tiers">
+    <wsdl:port name="Tiers" binding="impl:TiersSoapBinding">
+      <wsdlsoap:address location="http://10.1.20.153:28001/axis2/services/Tiers/"/>
+    </wsdl:port>
+  </wsdl:service>
+</wsdl:definitions>
diff --git a/tests/data/astregs/Tiers.xml b/tests/data/astregs/Tiers.xml
new file mode 100644
index 00000000..f7ac2a79
--- /dev/null
+++ b/tests/data/astregs/Tiers.xml
@@ -0,0 +1 @@
+<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns1:chargementResponse xmlns:ns1="http://gfi.astre.webservices/gf/tiers"><ns1:response><ns1:TiersReturn><ns1:Financier>true</ns1:Financier><ns1:CodeTiers>173957</ns1:CodeTiers><ns1:CodeFamille>51</ns1:CodeFamille><ns1:CatTiers>50</ns1:CatTiers><ns1:CodeCivilite></ns1:CodeCivilite><ns1:NomEnregistrement>ASSOCIATION OMNISPORTS DES MONTS D AZUR</ns1:NomEnregistrement><ns1:Nom></ns1:Nom><ns1:Prenom></ns1:Prenom><ns1:Sigle></ns1:Sigle><ns1:Organisme>CG06</ns1:Organisme><ns1:RaisonSociale3>ASSOCIATION OMNISPORTS DES</ns1:RaisonSociale3><ns1:RaisonSociale4>MONTS D&amp;#39;AZUR</ns1:RaisonSociale4><ns1:RaisonSociale5></ns1:RaisonSociale5><ns1:RaisonSociale6></ns1:RaisonSociale6><ns1:LibelleCourrier>ASS OMNISPORTS DES MONTS D AZUR</ns1:LibelleCourrier><ns1:EncodeKeyNatjur>F1</ns1:EncodeKeyNatjur><ns1:CodeAPE></ns1:CodeAPE><ns1:NumeroSiret>500433909</ns1:NumeroSiret><ns1:NumeroSiretFin>00016</ns1:NumeroSiretFin><ns1:Commentaire>Autres activités liées au sport (9319Z)</ns1:Commentaire><ns1:AdresseDestinataire>ASS OMNISPORTS DES MONTS D AZUR</ns1:AdresseDestinataire><ns1:AdresseTitre>ADRESSE PROFESSIONNELLE</ns1:AdresseTitre><ns1:IdentifiantAdresse>22791</ns1:IdentifiantAdresse><ns1:AdresseIsAdresseDeFacturation>true</ns1:AdresseIsAdresseDeFacturation><ns1:AdresseIsAdresseDeCommande>true</ns1:AdresseIsAdresseDeCommande><ns1:AdresseComplementDestinataire></ns1:AdresseComplementDestinataire><ns1:AdresseComplementaire></ns1:AdresseComplementaire><ns1:AdresseLibelleRue>271 CHEMIN DE CURNIER</ns1:AdresseLibelleRue><ns1:AdresseComplementVoie></ns1:AdresseComplementVoie><ns1:AdresseCodePostal>06750</ns1:AdresseCodePostal><ns1:AdresseBureauDistributeur>SERANON</ns1:AdresseBureauDistributeur><ns1:AdresseCodePays></ns1:AdresseCodePays><ns1:AdresseLibellePays>FRANCE</ns1:AdresseLibellePays><ns1:NumeroTelephone></ns1:NumeroTelephone><ns1:NumeroFax></ns1:NumeroFax><ns1:Mail></ns1:Mail><ns1:SiteWeb></ns1:SiteWeb><ns1:CodeTiersReprise>173957</ns1:CodeTiersReprise><ns1:StatutTiers>VALIDE</ns1:StatutTiers><ns1:Type>*</ns1:Type><ns1:Permanent>true</ns1:Permanent><ns1:IndSeuil>false</ns1:IndSeuil><ns1:DelaiSuiviFacture>0</ns1:DelaiSuiviFacture><ns1:Remise>0,00</ns1:Remise><ns1:DeclarationFiscale>false</ns1:DeclarationFiscale><ns1:IndicateurTiersSubrogatoire>false</ns1:IndicateurTiersSubrogatoire><ns1:ValeurIdentifiant0></ns1:ValeurIdentifiant0><ns1:ValeurIdentifiant1></ns1:ValeurIdentifiant1><ns1:ValeurIdentifiant2></ns1:ValeurIdentifiant2><ns1:ValeurIdentifiant3></ns1:ValeurIdentifiant3><ns1:ValeurIdentifiant4></ns1:ValeurIdentifiant4><ns1:ValeurIdentifiant5></ns1:ValeurIdentifiant5><ns1:ValeurIdentifiant6></ns1:ValeurIdentifiant6><ns1:ValeurIdentifiant7></ns1:ValeurIdentifiant7><ns1:ValeurIdentifiant8></ns1:ValeurIdentifiant8><ns1:ValeurIdentifiant9></ns1:ValeurIdentifiant9><ns1:NoDeclarationPref></ns1:NoDeclarationPref><ns1:TiersContactId>12967</ns1:TiersContactId><ns1:EncodeKeyContact>13012</ns1:EncodeKeyContact><ns1:EncodeKeyFonction></ns1:EncodeKeyFonction><ns1:LibelleFonction></ns1:LibelleFonction><ns1:DateDebutFonction></ns1:DateDebutFonction><ns1:DateFinFonction></ns1:DateFinFonction></ns1:TiersReturn></ns1:response></ns1:chargementResponse></soapenv:Body></soapenv:Envelope>
diff --git a/tests/test_astregs.py b/tests/test_astregs.py
new file mode 100644
index 00000000..63cd08a1
--- /dev/null
+++ b/tests/test_astregs.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+
+import os
+import mock
+import pytest
+
+from passerelle.apps.astregs.models import AstreGS, Link
+
+from . import utils
+
+BASE_URL = 'https://test-ws-astre-gs.departement06.fr/axis2/services/'
+
+def contact_search_side_effect(wsdl_url, **kwargs):
+    if 'Tiers' in wsdl_url:
+        response_content = file(os.path.join(os.path.dirname(__file__),
+                                'data', 'astregs', 'Tiers.xml')).read()
+    else:
+        response_content = file(os.path.join(os.path.dirname(__file__),
+                                'data', 'astregs', 'Contact.xml')).read()
+    return mock.Mock(content=response_content, status_code=200,
+                     headers={'Content-Type': 'text/xml'})
+
+def search_wsdl_side_effect(wsdl_url, **kwargs):
+    if 'Tiers' in wsdl_url:
+        response_content = file(os.path.join(os.path.dirname(__file__),
+                                'data', 'astregs', 'Tiers.wsdl')).read()
+    else:
+        response_content = file(os.path.join(os.path.dirname(__file__),
+                                'data', 'astregs', 'Contact.wsdl')).read()
+    return mock.Mock(content=response_content, status_code=200,
+                     headers={'Content-Type': 'text/xml'})
+
+
+@pytest.fixture
+def connector(db):
+    return utils.make_resource(AstreGS,
+            title='Test', slug='test',
+            description='test', wsdl_base_url=BASE_URL,
+            username='CS-FORML', password='secret',
+            organism='CG06', budget='01',
+            exercice='2019'
+    )
+
+
+@mock.patch('passerelle.utils.Request.get')
+@mock.patch('passerelle.utils.Request.post')
+def test_search_association_by_siren(mocked_post, mocked_get, connector, app):
+    wsdl_content = file(os.path.join(os.path.dirname(__file__),
+                                     'data', 'astregs', 'RechercheTiersDetails.wsdl')).read()
+    response_content = file(os.path.join(os.path.dirname(__file__),
+                                     'data', 'astregs', 'RechercheTiersDetails.xml')).read()
+    mocked_get.return_value = mock.Mock(content=wsdl_content)
+    mocked_post.return_value = mock.Mock(content=response_content, status_code=200,
+                                         headers={'Content-Type': 'text/xml'})
+    resp = app.get('/astregs/test/associations', params={'siren': '500433909'})
+    assert mocked_get.call_args[0][0] == '%sRechercheTiersDetails?wsdl' % BASE_URL
+    assert mocked_post.call_args[0][0] == '%sRechercheTiersDetails/' % BASE_URL
+    assert isinstance(resp.json['data'], list)
+    assert len(resp.json['data']) > 0
+    assert resp.json['data'][0]['id'] == '50043390900016'
+    assert resp.json['data'][0]['text'] == '50043390900016 - ASSOCIATION OMNISPORTS DES MONTS D AZUR'
+    assert resp.json['data'][0]['code'] == '173957'
+    assert resp.json['data'][0]['name'] == 'ASSOCIATION OMNISPORTS DES MONTS D AZUR'
+
+
+@mock.patch('passerelle.utils.Request.get')
+@mock.patch('passerelle.utils.Request.post')
+def test_check_association_presence(mocked_post, mocked_get, connector, app):
+    wsdl_content = file(os.path.join(os.path.dirname(__file__),
+                                     'data', 'astregs', 'RechercheTiers.wsdl')).read()
+    response_content = file(os.path.join(os.path.dirname(__file__),
+                                     'data', 'astregs', 'RechercheTiers.xml')).read()
+    mocked_get.return_value = mock.Mock(content=wsdl_content)
+    mocked_post.return_value = mock.Mock(content=response_content, status_code=200,
+                                         headers={'Content-Type': 'text/xml'})
+    resp = app.get('/astregs/test/check-association-by-siret', params={'siret': '50043390900014'})
+    assert resp.json['exists'] == True
+    response_content = file(os.path.join(os.path.dirname(__file__),
+                                     'data', 'astregs', 'RechercheTiersNoResult.xml')).read()
+    mocked_post.return_value = mock.Mock(content=response_content, status_code=200,
+                                         headers={'Content-Type': 'text/xml'})
+    resp = app.get('/astregs/test/check-association-by-siret', params={'siret': 'unknown'})
+    assert resp.json['exists'] == False
+
+
+@mock.patch('passerelle.utils.Request.get', side_effect=search_wsdl_side_effect)
+@mock.patch('passerelle.utils.Request.post', side_effect=contact_search_side_effect)
+def test_association_linking_means(mocked_post, mocked_get, client, connector, app):
+    resp = app.get('/astregs/test/get-association-link-means', params={'association_id': '42'})
+    assert len(resp.json['data']) == 3
+    for result in resp.json['data']:
+        assert 'id' in result
+        assert 'text' in result
+        assert 'type' in result
+        assert 'value' in result
+
+@mock.patch('passerelle.utils.Request.get', side_effect=search_wsdl_side_effect)
+@mock.patch('passerelle.utils.Request.post', side_effect=contact_search_side_effect)
+def test_link_user_to_association(mocked_post, mocked_get, client, connector, app):
+    assert Link.objects.count() == 0
+    resp = app.get('/astregs/test/get-association-link-means', params={'association_id': '42'})
+    assert len(resp.json['data']) == 3
+    resp = app.post_json('/astregs/test/link', params={'association_id': '42', 'NameID': 'user_name_id'})
+    assert Link.objects.filter(name_id='user_name_id', association_id='42').count() == 1
+    link = Link.objects.get(name_id='user_name_id', association_id='42')
+    assert resp.json['association_id'] == link.association_id
+    assert resp.json['link'] == link.pk
+    assert resp.json['created'] == True
+    resp = app.post_json('/astregs/test/link', params={'association_id': '42', 'NameID': 'user_name_id'})
+    assert resp.json['created'] == False
+
+
+@mock.patch('passerelle.utils.Request.get', side_effect=search_wsdl_side_effect)
+@mock.patch('passerelle.utils.Request.post', side_effect=contact_search_side_effect)
+def test_unlink_user_from_association(mocked_post, mocked_get, connector, app):
+    resp = app.get('/astregs/test/get-association-link-means', params={'association_id': '42'})
+    resp = app.post_json('/astregs/test/link', params={'association_id': '42', 'NameID': 'user_name_id'})
+    resp = app.get('/astregs/test/unlink', params={'NameID': 'user_name_id', 'association_id': '42'})
+    assert resp.json['deleted']
+    resp = app.get('/astregs/test/unlink', params={'NameID': 'user_name_id', 'association_id': '42'}, status=404)
-- 
2.20.1

