text: import simplejson as json
  import falcon
  import pytest
  from smpa.services.address import _addresses, _site_addresses
  from .util import purger
  
  
  SITE_ADDRESS_UUID = 'dcde565b-ff0b-4177-9c0b-f3d8d131ce02'
  
  
  def test_address_fixture(address):
      assert address.number == "42"
  
  
  def test_address_validates(address):
      assert address.validate() is None
  
  
  ####################################################################################################
  # Test the address service
  #
  # Some of these are marked as slow just because they access the database.
  #
  ####################################################################################################
  
  @pytest.mark.slow
  def test_address_save_and_get(address):
      a = _addresses.save(address)
      assert _addresses.count() == 1
      assert a.id is not None
      assert _addresses.get(a.id) is not None
      _addresses._purge()
      assert _addresses.count() == 0
  
  
  @pytest.mark.slow
  @purger(_addresses)
  def test_address_find(address):
      a = _addresses.save(address)
      assert len(_addresses.find(number='42')) > 0
      _addresses.delete(a)
      assert _addresses.count() == 0
  
  
  @purger(_addresses)
  def test_new(address):
      a = _addresses.new(
          number="23",
          property_name="The Big Building",
          address_line_1="A Street",
          address_line_2="Some district",
          address_line_3="Something else",
          town_city="London",
          postcode="N1 1NN"
      )
      assert a.validate() is None
  
  
  @pytest.mark.slow
  @purger(_addresses)
  def test_first(address):
      _site_addresses.get_or_create(postcode='W1T 1AH', town_city='London')
      sa = _site_addresses.first(postcode='W1T 1AH')
      assert sa is not None
      assert sa.town_city == 'London'
  
  
  @purger(_addresses)
  def test_get_value_error():
      with pytest.raises(ValueError):
          _addresses.get(id=None)
  
  
  @purger([_addresses, _site_addresses])
  def test_get_stringify_id():
      site_address = _site_addresses.get_or_create(
          id='dcde565b-ff0b-4177-9c0b-f3d8d131ce02'
      )
  
      assert site_address is not None
      site_address.address_line_1 = "12 Stephen Mews"
      site_address.town_city = "London"
      site_address.postcode = "W1T 1AH"
      site_address.description = "Hactar Towers"
      _site_addresses.save(site_address)
  
      import uuid
      id = uuid.UUID(SITE_ADDRESS_UUID)
      uuid_address = _site_addresses.get(id=id)
      str_address = _site_addresses.get(id=str(id))
      assert str_address is not None
      assert uuid_address is not None
  
  
  @purger(_addresses)
  def test_get_or_404_good():
      _site_addresses.get_or_create(id=SITE_ADDRESS_UUID)
      assert _site_addresses.get_or_404(SITE_ADDRESS_UUID) is not None
  
  
  @purger(_addresses)
  def test_get_or_404_bad():
      _site_addresses.get_or_create(id=SITE_ADDRESS_UUID)
      with pytest.raises(falcon.HTTPError) as e:
          res = _site_addresses.get_or_404(id='a3c09c6f-3774-4c2a-b425-3f300bc6b287')
  
  
  @purger(_addresses)
  def test_first_or_404_good():
      _site_addresses.get_or_create(id=SITE_ADDRESS_UUID)
      assert _site_addresses.first_or_404(id=SITE_ADDRESS_UUID) is not None
  
  
  @purger(_addresses)
  def test_first_or_404_bad():
      _site_addresses.get_or_create(id=SITE_ADDRESS_UUID)
      with pytest.raises(falcon.HTTPError) as e:
          res = _site_addresses.first_or_404(id='a3c09c6f-3774-4c2a-b425-3f300bc6b287')
  
  
  @purger(_addresses)
  def test_create():
      a = _addresses.create(postcode='N1 1NN')
      assert a is not None
      b = _addresses.first(postcode='N1 1NN')
      assert b is not None
  
  
  @purger(_addresses)
  def test_create_from_json():
      a = _addresses.create(json="""
          {
              "postcode": "N2 2NN"
          }
      """)
      assert a is not None
      b = _addresses.first(postcode='N2 2NN')
      assert b is not None
  
  
  @purger(_addresses)
  def test_create_multiple_from_json():
      a = _addresses.create(json="""
          [
              {
                  "postcode": "N2 2NN"
              },
              {
                  "postcode": "N3 3NN"
              }
          ]
      """)
      assert a is not None
      b = _addresses.first(postcode='N2 2NN')
      c = _addresses.first(postcode='N3 3NN')
      assert b is not None
      assert c is not None
  
  
  @purger(_addresses)
  def test_find_with_limit():
      rv = _addresses.create(json="""
          [
              {
                  "property_name": "1 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "3 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "2 name",
                  "postcode": "N2 2NN"
              }
          ]
      """)
      assert rv is not None
      a = _addresses.first(property_name='1 name')
      b = _addresses.first(property_name='2 name')
      c = _addresses.first(property_name='3 name')
      assert a is not None
      assert b is not None
      assert c is not None
      rv2 = _addresses.find(limit=1, postcode="N2 2NN")
      assert rv2 is not None
      rv3 = _addresses.find(limit=2, postcode="N2 2NN")
      assert len(rv3) == 2
  
  
  @purger(_addresses)
  def test_find_with_order():
      rv = _addresses.create(json="""
          [
              {
                  "property_name": "1 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "3 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "2 name",
                  "postcode": "N2 2NN"
              }
          ]
      """)
      assert rv is not None
      a = _addresses.first(property_name='1 name')
      b = _addresses.first(property_name='2 name')
      c = _addresses.first(property_name='3 name')
      assert a is not None
      assert b is not None
      assert c is not None
      rv2 = _addresses.find(order_by="property_name", postcode="N2 2NN")
      assert rv2[0].id == a.id
      assert rv2[1].id == b.id
      assert rv2[2].id == c.id
  
  
  @purger(_addresses)
  def test_all_with_limit():
      rv = _addresses.create(json="""
          [
              {
                  "property_name": "1 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "3 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "2 name",
                  "postcode": "N2 2NN"
              }
          ]
      """)
      assert rv is not None
      a = _addresses.first(property_name='1 name')
      b = _addresses.first(property_name='2 name')
      c = _addresses.first(property_name='3 name')
      assert a is not None
      assert b is not None
      assert c is not None
      rv2 = _addresses.all(limit=1)
      assert rv2 is not None
      rv3 = _addresses.all(limit=2)
      assert len(rv3) == 2
  
  
  @purger(_addresses)
  def test_all_with_order():
      rv = _addresses.create(json="""
          [
              {
                  "property_name": "1 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "3 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "2 name",
                  "postcode": "N2 2NN"
              }
          ]
      """)
      assert rv is not None
      a = _addresses.first(property_name='1 name')
      b = _addresses.first(property_name='2 name')
      c = _addresses.first(property_name='3 name')
      assert a is not None
      assert b is not None
      assert c is not None
      rv2 = _addresses.all(order_by="property_name")
      assert rv2[0].id == a.id
      assert rv2[1].id == b.id
      assert rv2[2].id == c.id
  
  
  @purger(_addresses)
  def test_all_with_order_reversed():
      rv = _addresses.create(json="""
          [
              {
                  "property_name": "1 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "3 name",
                  "postcode": "N2 2NN"
              },
              {
                  "property_name": "2 name",
                  "postcode": "N2 2NN"
              }
          ]
      """)
      assert rv is not None
      a = _addresses.first(property_name='1 name')
      b = _addresses.first(property_name='2 name')
      c = _addresses.first(property_name='3 name')
      assert a is not None
      assert b is not None
      assert c is not None
      rv2 = _addresses.all(order_by=">property_name")
      assert rv2[0].id == c.id
      assert rv2[1].id == b.id
      assert rv2[2].id == a.id
  
  
  @purger(_addresses)
  def test_get_or_create():
      a = _addresses.first(postcode='N1 1NN')
      assert a is None
      b = _addresses.get_or_create(postcode='N1 1NN')
      assert b is not None
      rv = _addresses.find(postcode='N1 1NN')
      assert len(rv) == 1
      # c should return the address created in b
      c = _addresses.get_or_create(postcode='N1 1NN')
      assert c is not None
      rv2 = _addresses.find(postcode='N1 1NN')
      assert len(rv2) == 1
  
  
  @purger(_addresses)
  def test_update():
      a = _addresses.get_or_create(
          postcode='N1 1NN'
      )
      assert a is not None
      _addresses.update(id=a.id, postcode='N9 9NN')
      b = _addresses.get(a.id)
      assert b is not None
      assert b.postcode == 'N9 9NN'
  
  
  @purger(_addresses)
  def test_update_with_no_changes():
      a = _addresses.get_or_create(
          postcode='N1 1NN'
      )
      assert a is not None
      _addresses.update(id=a.id, postcode='N1 1NN')
      b = _addresses.get(a.id)
      assert b is not None
      assert b.postcode == 'N1 1NN'
  
  
  @purger(_addresses)
  def test_bad_limit_exception():
      with pytest.raises(TypeError):
          a = _addresses.get_or_create(
              postcode='N1 1NN'
          )
          _addresses.all(limit='no')
  
  
  @purger(_addresses)
  def test_address_geojson(site_address):
      geo = """
          {
            "type": "FeatureCollection",
            "features": [
              {
                "type": "Feature",
                "id": "lu_blpu_planning_constraint.100021065242",
                "geometry": {
                  "type": "Polygon",
                  "coordinates": [
                    [
                      [
                        -0.04593036,
                        51.543539
                      ],
                      [
                        -0.04596475,
                        51.54352948
                      ],
                      [
                        -0.04606828,
                        51.54350083
                      ],
                      [
                        -0.04607099,
                        51.54350492
                      ],
                      [
                        -0.04609884,
                        51.54354495
                      ],
                      [
                        -0.04603026,
                        51.54356359
                      ],
                      [
                        -0.04600761,
                        51.54357041
                      ],
                      [
                        -0.04596092,
                        51.54358312
                      ],
                      [
                        -0.04589232,
                        51.54360221
                      ],
                      [
                        -0.04585953,
                        51.54361021
                      ],
                      [
                        -0.0458274,
                        51.54361956
                      ],
                      [
                        -0.04579682,
                        51.54357589
                      ],
                      [
                        -0.04582893,
                        51.54356698
                      ],
                      [
                        -0.04593036,
                        51.543539
                      ]
                    ]
                  ]
                },
                "geometry_name": "geom",
                "properties": {
                  "uprn": 100021065242,
                  "has_boundary": "yes",
                  "nb_a4d": 2,
                  "a4d_name": "Storage and Distribution to Residential, Light Industrial to Residential",
                  "nb_conarea": 1,
                  "conarea_name": "Victoria Park",
                  "nb_tpo": 0,
                  "tpo_name": "",
                  "is_listed_building": "0",
                  "is_floodzone_2": "0",
                  "is_floodzone_3a": "0",
                  "is_floodzone_3b": "0"
                }
              }
            ],
            "totalFeatures": 1,
            "numberMatched": 1,
            "numberReturned": 1,
            "timeStamp": "2019-07-05T14:10:20.720Z",
            "crs": {
              "type": "name",
              "properties": {
                "name": "urn:ogc:def:crs:EPSG::4326"
              }
            }
          }
      """
      site_address.siteGeoJson = json.loads(geo)
      _site_addresses.save(site_address)
      assert site_address.siteGeoJson is not None
      assert site_address.siteGeoJson.crs.type == 'name'
  
  
  # def test_first_and_last():
  #     a = _addresses.create(postcode='FIRST')
  #     b = _addresses.create(postcode='LAST')
  #     assert _addresses.count() == 2
  #     assert _addresses.last() == b
  #     assert _addresses.first() == a
  