From a6cb9cd24cfde9d178c39172c930c37648c76f0f Mon Sep 17 00:00:00 2001 From: Michael Wood Date: Mon, 16 Oct 2023 18:34:26 +0100 Subject: [PATCH] tests: Remove redundant backend tests Fix requirements as pytest-flask not yet compatible with flask 3. This leaves one very basic test which tests to see if the page loads without any javascript errors. Further tests are needed to test interactions. When we have a live backend for this this will be able to be added. --- .github/workflows/tests.yml | 2 +- requirements.in | 2 +- requirements.txt | 35 +- dev-requirements.in => requirements_dev.in | 3 +- requirements_dev.txt | 138 + tests/disabled_test_file_upload.py | 121 - .../360-giving-package-schema.json | 14 - tests/sample-data/360-giving-schema.json | 1317 ----- .../ExampleTrust-grants-broken.csv | 3 - .../ExampleTrust-grants-broken.xlsx | Bin 6393 -> 0 bytes .../sample-data/ExampleTrust-grants-fixed.csv | 11 - .../ExampleTrust-grants-fixed.json | 322 -- .../ExampleTrust-grants-fixed.xlsx | Bin 11173 -> 0 bytes .../ExampleTrust-grants-merged-cell.xlsx | Bin 11653 -> 0 bytes .../ExampleTrust-grants-metadata.xlsx | Bin 10308 -> 0 bytes tests/sample-data/schema.json | 5031 ----------------- tests/test_browser.py | 36 +- tests/test_commands.py | 75 - tests/test_db.py | 9 - tests/test_from_url.py | 68 - tests/test_insights.py | 115 - tests/test_utils.py | 130 - 22 files changed, 174 insertions(+), 7258 deletions(-) rename dev-requirements.in => requirements_dev.in (89%) create mode 100644 requirements_dev.txt delete mode 100644 tests/disabled_test_file_upload.py delete mode 100644 tests/sample-data/360-giving-package-schema.json delete mode 100644 tests/sample-data/360-giving-schema.json delete mode 100644 tests/sample-data/ExampleTrust-grants-broken.csv delete mode 100644 tests/sample-data/ExampleTrust-grants-broken.xlsx delete mode 100644 tests/sample-data/ExampleTrust-grants-fixed.csv delete mode 100644 tests/sample-data/ExampleTrust-grants-fixed.json delete mode 100644 tests/sample-data/ExampleTrust-grants-fixed.xlsx delete mode 100644 tests/sample-data/ExampleTrust-grants-merged-cell.xlsx delete mode 100644 tests/sample-data/ExampleTrust-grants-metadata.xlsx delete mode 100644 tests/sample-data/schema.json delete mode 100644 tests/test_commands.py delete mode 100644 tests/test_db.py delete mode 100644 tests/test_from_url.py delete mode 100644 tests/test_insights.py delete mode 100644 tests/test_utils.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 80bbf6b..9deb188 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,7 +27,7 @@ jobs: - name: Setup run: | python -m pip install --upgrade pip - pip install -r dev-requirements.txt + pip install -r requirements_dev.txt git submodule update --init --recursive - name: Test with pytest run: pytest tests/ --cov-append --cov diff --git a/requirements.in b/requirements.in index e3562d5..efc0315 100644 --- a/requirements.in +++ b/requirements.in @@ -1,3 +1,3 @@ -flask +flask==2.3 requests gunicorn diff --git a/requirements.txt b/requirements.txt index ad309dd..485d570 100755 --- a/requirements.txt +++ b/requirements.txt @@ -4,30 +4,33 @@ # # pip-compile requirements.in # -certifi==2021.5.30 +blinker==1.6.3 + # via flask +certifi==2023.7.22 # via requests -chardet==4.0.0 +charset-normalizer==3.3.0 # via requests -click==8.0.1 +click==8.1.7 # via flask -flask==2.0.1 +flask==2.3 # via -r requirements.in -gunicorn==20.1.0 +gunicorn==21.2.0 # via -r requirements.in -idna==2.10 +idna==3.4 # via requests -itsdangerous==2.0.1 +itsdangerous==2.1.2 # via flask -jinja2==3.0.1 +jinja2==3.1.2 # via flask -markupsafe==2.0.1 - # via jinja2 -requests==2.25.1 +markupsafe==2.1.3 + # via + # jinja2 + # werkzeug +packaging==23.2 + # via gunicorn +requests==2.31.0 # via -r requirements.in -urllib3==1.26.5 +urllib3==2.0.6 # via requests -werkzeug==2.0.1 +werkzeug==3.0.0 # via flask - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/dev-requirements.in b/requirements_dev.in similarity index 89% rename from dev-requirements.in rename to requirements_dev.in index b4b0008..9c0a4b0 100644 --- a/dev-requirements.in +++ b/requirements_dev.in @@ -2,10 +2,9 @@ black isort pytest -pytest-flask pytest-cov +pytest-flask coverage -requests_mock selenium chromedriver-autoinstaller coveralls diff --git a/requirements_dev.txt b/requirements_dev.txt new file mode 100644 index 0000000..ac95f92 --- /dev/null +++ b/requirements_dev.txt @@ -0,0 +1,138 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile requirements_dev.in +# +attrs==23.1.0 + # via + # outcome + # trio +black==23.9.1 + # via -r requirements_dev.in +blinker==1.6.3 + # via + # -r requirements.txt + # flask +certifi==2023.7.22 + # via + # -r requirements.txt + # requests + # selenium +charset-normalizer==3.3.0 + # via + # -r requirements.txt + # requests +chromedriver-autoinstaller==0.6.2 + # via -r requirements_dev.in +click==8.1.7 + # via + # -r requirements.txt + # black + # flask +coverage[toml]==6.5.0 + # via + # -r requirements_dev.in + # coveralls + # pytest-cov +coveralls==3.3.1 + # via -r requirements_dev.in +docopt==0.6.2 + # via coveralls +exceptiongroup==1.1.3 + # via + # pytest + # trio + # trio-websocket +flask==2.3 + # via + # -r requirements.txt + # pytest-flask +gunicorn==21.2.0 + # via -r requirements.txt +h11==0.14.0 + # via wsproto +idna==3.4 + # via + # -r requirements.txt + # requests + # trio +iniconfig==2.0.0 + # via pytest +isort==5.12.0 + # via -r requirements_dev.in +itsdangerous==2.1.2 + # via + # -r requirements.txt + # flask +jinja2==3.1.2 + # via + # -r requirements.txt + # flask +markupsafe==2.1.3 + # via + # -r requirements.txt + # jinja2 + # werkzeug +mypy-extensions==1.0.0 + # via black +outcome==1.2.0 + # via trio +packaging==23.2 + # via + # -r requirements.txt + # black + # gunicorn + # pytest +pathspec==0.11.2 + # via black +platformdirs==3.11.0 + # via black +pluggy==1.3.0 + # via pytest +pysocks==1.7.1 + # via urllib3 +pytest==7.4.2 + # via + # -r requirements_dev.in + # pytest-cov + # pytest-flask +pytest-cov==4.1.0 + # via -r requirements_dev.in +pytest-flask==1.2.0 + # via -r requirements_dev.in +requests==2.31.0 + # via + # -r requirements.txt + # coveralls +selenium==4.14.0 + # via -r requirements_dev.in +sniffio==1.3.0 + # via trio +sortedcontainers==2.4.0 + # via trio +tomli==2.0.1 + # via + # black + # coverage + # pytest +trio==0.22.2 + # via + # selenium + # trio-websocket +trio-websocket==0.11.1 + # via selenium +typing-extensions==4.8.0 + # via black +urllib3[socks]==2.0.6 + # via + # -r requirements.txt + # requests + # selenium +werkzeug==3.0.0 + # via + # -r requirements.txt + # flask + # pytest-flask +wsproto==1.2.0 + # via trio-websocket diff --git a/tests/disabled_test_file_upload.py b/tests/disabled_test_file_upload.py deleted file mode 100644 index 1f7f70f..0000000 --- a/tests/disabled_test_file_upload.py +++ /dev/null @@ -1,121 +0,0 @@ -import io -import os - -from flask import request -import pytest -import requests_mock - -from .test_insights import test_app, client - - -WORKING_FILES = [ - (r"sample-data/ExampleTrust-grants-fixed.csv", "csv"), - (r"sample-data/ExampleTrust-grants-fixed.xlsx", "xlsx"), - (r"sample-data/ExampleTrust-grants-fixed.json", "json"), - (r"sample-data/ExampleTrust-grants-merged-cell.xlsx", "xlsx"), -] -BROKEN_FILES = [ - (r"sample-data/ExampleTrust-grants-broken.csv", "csv"), - (r"sample-data/ExampleTrust-grants-broken.xlsx", "xlsx"), -] - - -@pytest.fixture -def get_file(): - thisdir = os.path.dirname(os.path.realpath(__file__)) - return lambda x: os.path.join(thisdir, x) - - -@pytest.fixture -def m(): - urls = [ - ( - r"sample-data/ExampleTrust-grants-fixed.json", - "https://grantnav.threesixtygiving.org/grants/grants.json", - "application/json", - ), - ( - r"sample-data/ExampleTrust-grants-fixed.xlsx", - "https://grantnav.threesixtygiving.org/grants/grants.xlsx", - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - ), - ( - r"sample-data/ExampleTrust-grants-fixed.csv", - "https://grantnav.threesixtygiving.org/grants/grants.csv", - "text/csv", - ), - ( - r"sample-data/ExampleTrust-grants-broken.csv", - "https://grantnav.threesixtygiving.org/grants/broken-grants.csv", - "text/csv", - ), - ( - r"sample-data/360-giving-package-schema.json", - "https://raw.githubusercontent.com/ThreeSixtyGiving/standard/master/schema/360-giving-package-schema.json", - "application/json", - ), - ( - r"sample-data/360-giving-schema.json", - "https://raw.githubusercontent.com/ThreeSixtyGiving/standard/master/schema/360-giving-schema.json", - "application/json", - ), - # (r'sample_external_apis/registry.json', - # 'https://store.data.threesixtygiving.org/reports/daily_status.json'), - # (r"sample_external_apis/ftc/GB-CHC-225922.json", - # re.compile('https://findthatcharity.uk/orgid/')), - # (r"sample_external_apis/ch/04325234.json", - # re.compile('http://data.companieshouse.gov.uk/')), - # (r'sample_external_apis/pc/SE1 1AA.json', - # re.compile('https://findthatpostcode.uk/postcodes/')), - # (r'sample_external_apis/geonames.csv', - # 'https://findthatpostcode.uk/areas/names.csv?types=ctry,cty,laua,pcon,rgn,imd,ru11ind,oac11,lat,long'), - ] - - m = requests_mock.Mocker() - thisdir = os.path.dirname(os.path.realpath(__file__)) - for i in urls: - with open(os.path.join(thisdir, i[0]), "rb") as f_: - m.get(i[1], content=f_.read(), headers={"Content-Type": i[2]}) - m.head(i[1], headers={"Content-Type": i[2]}) - - m.start() - return m - - -@pytest.mark.parametrize("filename,filetype", WORKING_FILES) -def test_upload(m, client, filename, filetype): - thisdir = os.path.dirname(os.path.realpath(__file__)) - with open(os.path.join(thisdir, filename), "rb") as f_: - data = {"file": (io.BytesIO(f_.read()), filename.split("/")[1])} - rv = client.post( - "/upload", - data=data, - follow_redirects=True, - content_type="multipart/form-data", - ) - assert rv.status_code == 200 - assert rv.json["rows_saved"] == 10 - assert rv.json["filetype"] == filetype - - data_page = client.get(rv.json["data_url"]) - assert data_page.status_code == 200 - assert rv.json["dataset"].encode("utf8") in data_page.data - - -@pytest.mark.parametrize("filename,filetype", BROKEN_FILES) -def test_upload_broken(m, client, filename, filetype): - thisdir = os.path.dirname(os.path.realpath(__file__)) - with open(os.path.join(thisdir, filename), "rb") as f_: - data = {"file": (io.BytesIO(f_.read()), filename.split("/")[1])} - rv = client.post( - "/upload", - data=data, - follow_redirects=True, - content_type="multipart/form-data", - ) - assert rv.status_code == 400 - assert "error" in rv.json - assert rv.json.get("rows_saved", 0) == 0 - assert rv.json["filetype"] == filetype - - diff --git a/tests/sample-data/360-giving-package-schema.json b/tests/sample-data/360-giving-package-schema.json deleted file mode 100644 index 075f7c2..0000000 --- a/tests/sample-data/360-giving-package-schema.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Schema for a 360Giving Data Grant Package", - "type": "object", - "required": ["grants"], - "properties": { - "grants": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://raw.githubusercontent.com/ThreeSixtyGiving/standard/master/schema/360-giving-schema.json" }, - "uniqueItems": true - } - } -} diff --git a/tests/sample-data/360-giving-schema.json b/tests/sample-data/360-giving-schema.json deleted file mode 100644 index 265a8ab..0000000 --- a/tests/sample-data/360-giving-schema.json +++ /dev/null @@ -1,1317 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "360Giving Data Standard Schema", - "type": "object", - "definitions": { - "currency": { - "type": "string", - "description": "The currency used in amounts. Use the three-letter currency code from [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) eg: Use GBP for Pounds Sterling.", - "weight": 5.02, - "enum": [ - "ADP", - "AED", - "AFA", - "AFN", - "ALK", - "ALL", - "AMD", - "ANG", - "AOA", - "AOK", - "AON", - "AOR", - "ARA", - "ARP", - "ARS", - "ARY", - "ATS", - "AUD", - "AWG", - "AYM", - "AZM", - "AZN", - "BAD", - "BAM", - "BBD", - "BDT", - "BEC", - "BEF", - "BEL", - "BGJ", - "BGK", - "BGL", - "BGN", - "BHD", - "BIF", - "BMD", - "BND", - "BOB", - "BOP", - "BOV", - "BRB", - "BRC", - "BRE", - "BRL", - "BRN", - "BRR", - "BSD", - "BTN", - "BUK", - "BWP", - "BYB", - "BYN", - "BYR", - "BZD", - "CAD", - "CDF", - "CHC", - "CHE", - "CHF", - "CHW", - "CLF", - "CLP", - "CNY", - "COP", - "COU", - "CRC", - "CSD", - "CSJ", - "CSK", - "CUC", - "CUP", - "CVE", - "CYP", - "CZK", - "DDM", - "DEM", - "DJF", - "DKK", - "DOP", - "DZD", - "ECS", - "ECV", - "EEK", - "EGP", - "ERN", - "ESA", - "ESB", - "ESP", - "ETB", - "EUR", - "FIM", - "FJD", - "FKP", - "FRF", - "GBP", - "GEK", - "GEL", - "GHC", - "GHP", - "GHS", - "GIP", - "GMD", - "GNE", - "GNF", - "GNS", - "GQE", - "GRD", - "GTQ", - "GWE", - "GWP", - "GYD", - "HKD", - "HNL", - "HRD", - "HRK", - "HTG", - "HUF", - "IDR", - "IEP", - "ILP", - "ILR", - "ILS", - "INR", - "IQD", - "IRR", - "ISJ", - "ISK", - "ITL", - "JMD", - "JOD", - "JPY", - "KES", - "KGS", - "KHR", - "KMF", - "KPW", - "KRW", - "KWD", - "KYD", - "KZT", - "LAJ", - "LAK", - "LBP", - "LKR", - "LRD", - "LSL", - "LSM", - "LTL", - "LTT", - "LUC", - "LUF", - "LUL", - "LVL", - "LVR", - "LYD", - "MAD", - "MDL", - "MGA", - "MGF", - "MKD", - "MLF", - "MMK", - "MNT", - "MOP", - "MRO", - "MRU", - "MTL", - "MTP", - "MUR", - "MVQ", - "MVR", - "MWK", - "MXN", - "MXP", - "MXV", - "MYR", - "MZE", - "MZM", - "MZN", - "NAD", - "NGN", - "NIC", - "NIO", - "NLG", - "NOK", - "NPR", - "NZD", - "OMR", - "PAB", - "PEH", - "PEI", - "PEN", - "PES", - "PGK", - "PHP", - "PKR", - "PLN", - "PLZ", - "PTE", - "PYG", - "QAR", - "RHD", - "ROK", - "ROL", - "RON", - "RSD", - "RUB", - "RUR", - "RWF", - "SAR", - "SBD", - "SCR", - "SDD", - "SDG", - "SDP", - "SEK", - "SGD", - "SHP", - "SIT", - "SKK", - "SLL", - "SOS", - "SRD", - "SRG", - "SSP", - "STD", - "STN", - "SUR", - "SVC", - "SYP", - "SZL", - "THB", - "TJR", - "TJS", - "TMM", - "TMT", - "TND", - "TOP", - "TPE", - "TRL", - "TRY", - "TTD", - "TWD", - "TZS", - "UAH", - "UAK", - "UGS", - "UGW", - "UGX", - "USD", - "USN", - "USS", - "UYI", - "UYN", - "UYP", - "UYU", - "UZS", - "VEB", - "VEF", - "VNC", - "VND", - "VUV", - "WST", - "XAF", - "XAG", - "XAU", - "XBA", - "XBB", - "XBC", - "XBD", - "XCD", - "XDR", - "XEU", - "XFO", - "XFU", - "XOF", - "XPD", - "XPF", - "XPT", - "XRE", - "XSU", - "XTS", - "XUA", - "XXX", - "YDD", - "YER", - "YUD", - "YUM", - "YUN", - "ZAL", - "ZAR", - "ZMK", - "ZMW", - "ZRN", - "ZRZ", - "ZWC", - "ZWD", - "ZWL", - "ZWN", - "ZWR" - ], - "title": "Currency" - }, - "Transaction": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Identifier", - "weight": 0.001, - "title": "Identifier" - }, - "transactionDate": { - "oneOf": [ - {"format": "date-time"}, - {"pattern":"^[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$"} - ], - "type": "string", - "description": "When did this transaction take place? The date should be written as YYYY-MM-DD, or in full date-time format.", - "weight": 5, - "title": "Transaction Date" - }, - "currency": { - "$ref": "#/definitions/currency" - }, - "value": { - "type": "number", - "description": "The total value of this transaction.", - "weight": 6, - "title": "Value" - }, - "valueDate": { - "oneOf": [ - {"format": "date-time"}, - {"pattern":"^[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$"} - ], - "type": [ - "string", - "null" - ], - "description": "The date that this value was set (to allow historical currency conversion). The date should be written as YYYY-MM-DD, or in full date-time format.", - "weight": 6.1, - "title": "Value Date" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "A description of this transaction.", - "weight": 9, - "title": "Description" - }, - "provider": { - "type": [ - "string", - "null" - ], - "description": "The organisation identifier of the provider of transaction funds.", - "weight": 0.6, - "title": "Provider" - }, - "recipient": { - "type": [ - "string", - "null" - ], - "description": "The organisation identifier of the recipient of transaction funds.", - "weight": 0.7, - "title": "Recipient" - }, - "dateModified": { - "format": "date-time", - "type": "string", - "description": "When was information about this transaction last updated? A full date-time should be given. Usually this can be generated automatically by the software managing or exporting this data.", - "weight": 25, - "title": "Last Modified" - } - } - }, - "Documents": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "An identifier for this document.", - "weight": 0.001, - "title": "Identifier" - }, - "title": { - "type": [ - "string", - "null" - ], - "description": "The document title", - "weight": 1.05, - "title": "Title" - }, - "url": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "The URL of the document.", - "weight": 11.01, - "title": "Web Address" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "A description of the document", - "weight": 9, - "title": "Description" - }, - "documentType": { - "type": [ - "string", - "null" - ], - "description": "A document category. For example, 'Application Form', 'Photo' or 'Project Report'. In future, 360Giving will provide a codelist of document types.", - "weight": 0.8, - "title": "Document Type" - }, - "dateModified": { - "format": "date-time", - "type": "string", - "description": "What was this information last modified? A full date-time should be given. Usually this can be generated automatically by the software managing or exporting this data.", - "weight": 25, - "title": "Last Modified" - } - } - }, - "Location": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Location identifier", - "weight": 0.001, - "title": "Identifier" - }, - "name": { - "type": [ - "string", - "null" - ], - "description": "A name for this location.", - "weight": 1.1, - "title": "Name" - }, - "countryCode": { - "type": [ - "string", - "null" - ], - "enum": [ - "AF", - "AX", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "KH", - "CM", - "CA", - "CV", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CG", - "CD", - "CK", - "CR", - "CI", - "HR", - "CU", - "CW", - "CY", - "CZ", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MK", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "RE", - "RO", - "RU", - "RW", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SZ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "US", - "UM", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW" - ], - "description": "The ISO Country Code of the location of this activity.", - "weight": 2, - "title": "Country Code" - }, - "latitude": { - "type": [ - "number", - "null" - ], - "description": "The latitude of a point location", - "weight": 4.001, - "title": "Latitude" - }, - "longitude": { - "type": [ - "number", - "null" - ], - "description": "The longitude of a point location", - "weight": 4.002, - "title": "Longitude" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "A description of this location. This could include details of the element of the activity that takes place here.", - "weight": 9, - "title": "Description" - }, - "geoCode": { - "type": [ - "string", - "null" - ], - "description": "A code referring to a geographical area, drawn from an established gazetteer. For example, the code for a local authority ward, or parliamentary constituency.", - "weight": 5, - "title": "Geographic Code" - }, - "geoCodeType": { - "type": [ - "string", - "null" - ], - "description": "The type of Geographic Code (geoCode) used (e.g. Ward, Parliamentary Constituency etc.). This value for this field should be drawn from the [codelist of geographic code types](https://github.com/ThreeSixtyGiving/standard/tree/master/codelists/geoCodeType.csv).", - "weight": 5.01, - "title": "Geographic Code Type" - }, - "dateModified": { - "format": "date-time", - "type": "string", - "description": "When was this location information last modified? A full date-time should be given. Usually this can be generated automatically by the software managing or exporting this data.", - "weight": 25, - "title": "Last Modified" - } - } - }, - "Classification": { - "type": "object", - "properties": { - "vocabulary": { - "type": "string", - "description": "A vocabulary used for this classification.", - "weight": 8, - "title": "Vocabulary" - }, - "code": { - "type": "string", - "description": "A codelist value in the chosen vocabulary.", - "weight": 9, - "title": "Code" - }, - "title": { - "type": [ - "string", - "null" - ], - "description": "The title of this classification.", - "weight": 1.05, - "title": "Title" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "A description of this classification.", - "weight": 9, - "title": "Description" - }, - "url": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "A web link to more details of this classification.", - "weight": 9, - "title": "URL" - }, - "dateModified": { - "format": "date-time", - "type": "string", - "description": "When was this grant classification information last modified? A full date-time should be given. Usually this can be generated automatically by the software managing or exporting this data.", - "weight": 25, - "title": "Last Modified" - } - } - }, - "GrantProgramme": { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "An identifier for this grant programme.", - "weight": 9, - "title": "Code" - }, - "title": { - "type": [ - "string", - "null" - ], - "description": "The title of this grant programme.", - "weight": 1.05, - "title": "Title" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "A description of this grant programme.", - "weight": 9, - "title": "Description" - }, - "url": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "A web link to more details of this grant programme.", - "weight": 9, - "title": "URL" - }, - "dateModified": { - "format": "date-time", - "type": "string", - "description": "When was the link between this grant and its grant programme last modified? A full date-time should be given. Usually this can be generated automatically by the software managing or exporting this data.", - "weight": 25, - "title": "Last Modified" - } - } - }, - "Organization": { - "type": "object", - "required": [ - "id", - "name" - ], - "properties": { - "id": { - "type": "string", - "description": "A globally unique identifier for this organisation. This is important to enable data on funders and recipients to be linked up across different grant-makers. The [Organisation Identifier Standard](http://www.threesixtygiving.org/standard/identifiers/#toc-organisation-identifier) guidance explains how to create this ID, based either on the known company or charity number, or upon identifiers held in the grant-maker's internal systems.", - "weight": 0.001, - "title": "Identifier" - }, - "name": { - "type": "string", - "description": "Organisation name", - "weight": 1.1, - "title": "Name" - }, - "department": { - "type": "string", - "description": "The department or sub-unit of this organisation making or receiving the grant.", - "title": "Department" - }, - "contactName": { - "type": "string", - "description": "The contact person at this organisation.", - "weight": 2, - "title": "Contact Name" - }, - "charityNumber": { - "type": "string", - "description": "Registered charity number, if applicable.", - "weight": 6.01, - "title": "Charity Number" - }, - "companyNumber": { - "type": "string", - "description": "Registered UK company number, if applicable.", - "weight": 6.02, - "title": "Company Number" - }, - "streetAddress": { - "type": "string", - "description": "Building number and street name.", - "weight": 3.1, - "title": "Street Address" - }, - "addressLocality": { - "type": "string", - "description": "City or town.", - "weight": 3.2, - "title": "City" - }, - "addressRegion": { - "type": "string", - "description": "County", - "weight": 3.3, - "title": "County" - }, - "addressCountry": { - "type": "string", - "description": "Country", - "weight": 3.5, - "title": "Country" - }, - "postalCode": { - "type": "string", - "description": "Postal code (please try and provide a post code whenever possible)", - "weight": 3.4, - "title": "Postal Code" - }, - "telephone": { - "type": "string", - "description": "Contact phone number.", - "weight": 3.5, - "title": "Phone Number" - }, - "alternateName": { - "type": "string", - "description": "An alternative name for this organisation (e.g. trading name)", - "weight": 6, - "title": "Alternate Name" - }, - "email": { - "type": "string", - "description": "The email address for this organisation.", - "weight": 5, - "title": "Email" - }, - "description": { - "type": "string", - "description": "A short description of this organisation and its area of work", - "weight": 9, - "title": "Description" - }, - "organisationType": { - "type": [ - "string", - "null" - ], - "description": "A description of this organisation", - "enum": [ - "Registered Charity", - "Registered Company", - "Community Group", - "List to be updated" - ], - "weight": 5, - "title": "Organisation Type" - }, - "url": { - "type": "string", - "format": "uri", - "description": "A web address for the Organisation", - "weight": 11.01, - "title": "Web Address" - }, - "location": { - "items": { - "$ref": "#/definitions/Location" - }, - "type": "array", - "description": "-", - "weight": 5, - "title": "Location" - }, - "dateModified": { - "format": "date-time", - "type": "string", - "description": "When was the organisation information for this grant last modified? A full date-time should be given. Usually this can be generated automatically by the software managing or exporting this data.", - "weight": 25, - "title": "Last Modified" - } - } - }, - "Event": { - "definitions": {}, - "type": "object", - "title": "Event", - "description": "An event in the life of the grant activity", - "properties": { - "title": { - "type": "string", - "title":"Title", - "description": "The title of this event", - "weight": 1.05, - "title": "Title" - }, - "startDate": { - "oneOf": [ - {"format": "date-time"}, - {"pattern":"^[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$"}, - {"pattern":"^[0-9]{4}(-(0[1-9]|1[012]))?$"} - ], - "type": "string", - "description": "All events should have a start date. Dates should be in YYYY-MM-DD or date-time format. If the month or day are not available, these may be omitted.", - "weight": 4.1, - "title": "Start Date" - }, - "endDate": { - "oneOf": [ - {"format": "date-time"}, - {"pattern":"^[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$"}, - {"pattern":"^[0-9]{4}(-(0[1-9]|1[012]))?$"} - ], - "type": "string", - "description": "An end date for the grant. Dates should be in YYYY-MM-DD or date-time format. If the month or day are not available, these may be omitted.", - "weight": 4.3, - "title": "End Date" - }, - "duration": { - "type": "number", - "minimum": 0, - "description": "The duration of the grant, in months. Must be in number format.", - "weight": 4.2, - "title": "Duration (months)" - }, - "description": { - "type": "string", - "description": "A description of this event", - "weight": 9, - "title": "Description" - }, - "dateModified": { - "format": "date-time", - "type": "string", - "description": "When was information about this event last modified? A full date-time should be given. Usually this can be generated automatically by the software managing or exporting this data.", - "weight": 25, - "title": "Last Modified" - } - } - } - }, - "required": [ - "id", - "title", - "description", - "currency", - "amountAwarded", - "awardDate", - "recipientOrganization", - "fundingOrganization" - ], - "properties": { - "id": { - "type": "string", - "description": "The unique identifier for this grant. Made up of your 360Giving prefix, and an identifier from your records. See the [360Giving Grant identifier guidance](http://www.threesixtygiving.org/standard/identifiers/#toc-grant-identifier) for details.", - "weight": 0.001, - "title": "Identifier" - }, - "title": { - "type": "string", - "description": "A title for this grant activity. This should be under 140 characters long.", - "weight": 1.05, - "title": "Title" - }, - "description": { - "type": "string", - "description": "A short description of this grant activity.", - "weight": 9, - "title": "Description" - }, - "currency": { - "$ref": "#/definitions/currency" - }, - "amountAppliedFor": { - "type": "number", - "description": "Total amount applied for in numbers (do not include commas or currency symbols such as \u00a3). If you have provided detailed transaction information on a separate table, this should equal the sum of all the application transactions for this grant.", - "weight": 5.03, - "title": "Amount Applied For" - }, - "amountAwarded": { - "type": "number", - "description": "Total amount awarded in numbers (do not include commas or currency symbols such as \u00a3). If you have provided detailed transaction information on a separate table, this should equal the sum of all the award transactions for this grant.", - "weight": 5.04, - "title": "Amount Awarded" - }, - "amountDisbursed": { - "type": "number", - "description": "Total amount disbursed (paid) to this grantee when this record was last updated (in numbers: do not include commas or currency symbols such as \u00a3)). If you have provided detailed transaction information on a separate table, this should equal the sum of all the disbursement transactions for this grant.", - "weight": 5.04, - "title": "Amount Disbursed" - }, - "awardDate": { - "oneOf": [ - {"format": "date-time"}, - {"pattern":"^[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$"} - ], - "type": "string", - "description": "When was the decision to award this grant made. The date should be written as YYYY-MM-DD, or in full date-time format.", - "weight": 4.3, - "title": "Award Date" - }, - "url": { - "type": "string", - "format": "uri", - "description": "A URL (Web Address) where further information about this grant can be found. This could point to the website of the recipient organisation, or might link to further details on the funders website.", - "weight": 11.01, - "title": "URL" - }, - "plannedDates": { - "items": { - "$ref": "#/definitions/Event" - }, - "type": "array", - "weight": 5.041, - "title": "Planned Dates", - "description":"When the recipient organisation intends this activity to take place. A date range can include a start date and duration in months, or a start and end date.", - "rollUp": [ - "startDate", - "endDate", - "duration" - ] - }, - "actualDates": { - "items": { - "$ref": "#/definitions/Event" - }, - "type": "array", - "description": "When did this grant activity actually take place. Dates should be in YYYY-MM-DD format. A date range can include a start date and duration in months, or a start and end date.", - "weight": 5.041, - "title": "Actual Dates" - }, - "recipientOrganization": { - "items": { - "$ref": "#/definitions/Organization" - }, - "minItems": 1, - "type": "array", - "weight": 5, - "title": "Recipient Org", - "description":"Details of the recipient of this grant.", - "rollUp": [ - "id", - "name", - "charityNumber", - "companyNumber", - "streetAddress", - "addressLocality", - "addressRegion", - "postalCode", - "addressCountry", - "description", - "url" - ] - }, - "beneficiaryLocation": { - "items": { - "$ref": "#/definitions/Location" - }, - "type": "array", - "weight": 6.01, - "title": "Beneficiary Location", - "description": "Information about the location of beneficiaries. Further information about beneficiaries can be provided through classifications.", - "rollUp": [ - "name", - "countryCode", - "latitude", - "longitude", - "geoCode", - "geoCodeType" - ] - }, - "fundingOrganization": { - "items": { - "$ref": "#/definitions/Organization" - }, - "minItems": 1, - "type": "array", - "description": "Details of the funder", - "weight": 4, - "title": "Funding Org", - "rollUp": [ - "id", - "name", - "department" - ] - }, - "grantProgramme": { - "items": { - "$ref": "#/definitions/GrantProgramme" - }, - "type": "array", - "description": "-", - "weight": 5, - "title": "Grant Programme", - "rollUp": [ - "code", - "title", - "url" - ] - }, - "fromOpenCall": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "description": "Was this grant made as the result of an open call for applications? Values should be 'Yes' or 'No'", - "weight": 12, - "title": "From An Open Call?" - }, - "fundingType": { - "items": { - "$ref": "#/definitions/Classification" - }, - "type": "array", - "description": "-", - "weight": 5, - "title": "Funding Type" - }, - "classifications": { - "items": { - "$ref": "#/definitions/Classification" - }, - "type": "array", - "description": "-", - "weight": 5, - "title": "Classifications" - }, - "relatedDocument": { - "items": { - "$ref": "#/definitions/Documents" - }, - "type": "array", - "description": "-", - "weight": 5, - "title": "Related Document" - }, - "applicationTransaction": { - "items": { - "$ref": "#/definitions/Transaction" - }, - "type": "array", - "description": "-", - "weight": 5.02 - }, - "commitmentTransaction": { - "items": { - "$ref": "#/definitions/Transaction" - }, - "type": "array", - "description": "-", - "weight": 5.02 - }, - "disbursementTransaction": { - "items": { - "$ref": "#/definitions/Transaction" - }, - "type": "array", - "description": "-", - "weight": 5 - }, - "relatedActivity": { - "type": "array", - "items": { - "type": "string" - }, - "description": "The identifiers of any related activities (e.g. other grants given as part of a multi-grant project)", - "weight": 15, - "title": "Related Activity" - }, - "dateModified": { - "format": "date-time", - "type": "string", - "description": "When was information on this grant last updated? A full date-time should be given. Usually this can be generated automatically by the software managing or exporting this data.", - "weight": 25, - "title": "Last Modified" - }, - "dataSource": { - "format": "uri", - "type": [ - "string", - "null" - ], - "description": "A web link pointing to the source of this data. This may be an original 360Giving data file, a file from which the data was converted, or an organisation website.", - "weight": 25, - "title": "Data Source" - } - } -} diff --git a/tests/sample-data/ExampleTrust-grants-broken.csv b/tests/sample-data/ExampleTrust-grants-broken.csv deleted file mode 100644 index 877556c..0000000 --- a/tests/sample-data/ExampleTrust-grants-broken.csv +++ /dev/null @@ -1,3 +0,0 @@ -Identifier,Grant number,Surname of applicant,Full name of applicant,Grant type,Department,School / Building,Recipient Org:Identifier,Recipient Org:Name,Recipient Org:Company Number,Recipient Org:City,Title,Planned Dates:Duration (months),Amount Awarded,Currency,Award Date,Grant Programme:Code,Grant Programme:Title,Funding Org:Identifier,Funding Org:Name,Last modified,Data source -360G-sampletrust-105177/Z/14/Z,105177/Z/14/Z,Smith,Miss Jane Smith,Large Example Awards ,,,,Example Project Limited ,,London ,A n initiative,30,100000,GBP,24/07/2014,AAC,Arts Awards Funding Committee,GB-CHC-1234567,Example Trust,13-03-2015,http://www.example.org/grants.htm -360G-sampletrust-105182/Z/14/Z,105182/Z/14/Z,Jones,,Large Example Awards ,Department of Example Studies ,,GB-COH-RC000659,UNIVERSITY OF EXAMPLE,RC000659,City,A project ,25,1000,GBP,24/07/2014,AAC,Arts Awards Funding Committee,GB-CHC-1234567,Example Trust,13-03-2015,http://www.example.org/grants.htm diff --git a/tests/sample-data/ExampleTrust-grants-broken.xlsx b/tests/sample-data/ExampleTrust-grants-broken.xlsx deleted file mode 100644 index edc61b6bbb0042c254daf5f8f4e94d9c0e6ae420..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6393 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 Yh^?t|57{FD04(G$5t(`&(%ZZL0q`@-x&QzG diff --git a/tests/sample-data/ExampleTrust-grants-fixed.csv b/tests/sample-data/ExampleTrust-grants-fixed.csv deleted file mode 100644 index aec5990..0000000 --- a/tests/sample-data/ExampleTrust-grants-fixed.csv +++ /dev/null @@ -1,11 +0,0 @@ -Identifier,Title,Description,Currency,Amount Applied For,Amount Awarded,Amount Disbursed,Award Date,URL,Planned Dates:Start Date,Planned Dates:End Date,Planned Dates:Duration (months),Recipient Org:Identifier,Recipient Org:Name,Recipient Org:Charity Number,Recipient Org:Company Number,Recipient Org:Street Address,Recipient Org:City,Recipient Org:County,Recipient Org:Country,Recipient Org:Postal Code,Recipient Org:Description,Recipient Org:Web Address,Beneficiary Location:Name,Beneficiary Location:Country Code,Beneficiary Location:Latitude,Beneficiary Location:Longitude,Beneficiary Location:Geographic Code,Beneficiary Location:Geographic Code Type,Funding Org:Identifier,Funding Org:Name,Funding Org:Department,Grant Programme:Code,Grant Programme:Title,Grant Programme:URL,From an open call?,Related Activity,Last modified,Data Source -360G-KJD-001230,Grant award to Blue Trust,Towards respite day trips for young carers,GBP,,5000,,2017-12-08,,,,,GB-CHC-265374,Blue Trust,,,,,,,,,,North East England,GB,,,E12000001,RGN/GOR,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm -360G-KJD-001231,Grant award to Red Charity,Towards the salary of an advice worker,GBP,,10000,,2017-12-08,,,,,GB-CHC-1102541,Red Charity,,,,,,,,,,South West England,GB,,,E12000009,RGN/GOR,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm -360G-KJD-001232,Grant award to Green House Charity,Towards the purchase of a new minibus,GBP,,3500,,2017-12-08,,,,,GB-SC-SC065843,Green House Charity,,,,,,,,,,Scotland,GB,,,S92000003 ,CTRY,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm -360G-KJD-001233,Grant award to Purple Community Group,Towards the purchase of IT equipment,GBP,,2000,,2017-12-08,,,,,GB-REV-XN65729,Purple Community Group,,,,,,,,,,Northern Ireland,GB,,,N92000002,CTRY,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm -360G-KJD-001234,Grant award to Yellow Day Centre,Towards the core costs of the centre,GBP,,4500,,2017-12-08,,,,,GB-COH-08435647,Yellow Day Centre,,,,,,,,,,London,GB,,,E12000007,RGN/GOR,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm -360G-KJD-001235,Grant award to Orange Gardens,Towards the rebuilding of the historic orangery,GBP,,15000,,2017-12-08,,,,,GB-COH-07345264,Orange Gardens,,,,,,,,,,Wales,GB,,,W92000004,CTRY,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm -360G-KJD-001236,Grant award to Turquiose Foundation,Towards the redevelopment of the website,GBP,,1500,,2017-12-08,,,,,GB-CHC-1103425,Turquiose Foundation,,,,,,,,,,Yorkshire and The Humber,GB,,,E12000003,RGN/GOR,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm -360G-KJD-001237,Grant award to Pink Playing Field,Towards the maintenance of the field,GBP,,2500,,2017-12-08,,,,,360G-KJD-ORG:Pink_Playing_Field,Pink Playing Field,,,,,,,,,,East Midlands,GB,,,E12000004,RGN/GOR,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm -360G-KJD-001238,Grant award to Maroon Gallery,Towards the annual art exhibition at the Maroon Gallery,GBP,,7500,,2017-12-08,,,,,GB-COH-07564986,Maroon Gallery,,,,,,,,,,East Midlands,GB,,,E12000004,RGN/GOR,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm -360G-KJD-001239,Grant award to Grey Scout Group,Towards the roof repairs for the scout hut,GBP,,8250,,2017-12-08,,,,,360G-KJD-ORG:Grey_Scout_Group,Grey Scout Group,,,,,,,,,,North West England,GB,,,E12000002,RGN/GOR,GB-CHC-301077,K J D Foundation,,,,,,,2017-12-22T00:00:00Z,http://www.example.org/grants.htm diff --git a/tests/sample-data/ExampleTrust-grants-fixed.json b/tests/sample-data/ExampleTrust-grants-fixed.json deleted file mode 100644 index f0b5ee6..0000000 --- a/tests/sample-data/ExampleTrust-grants-fixed.json +++ /dev/null @@ -1,322 +0,0 @@ -{ - "grants": [ - { - "id": "360G-KJD-001230", - "title": "Grant award to Blue Trust", - "description": "Towards respite day trips for young carers", - "currency": "GBP", - "amountAwarded": 5000, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "GB-CHC-265374", - "name": "Blue Trust" - } - ], - "beneficiaryLocation": [ - { - "name": "North East England", - "countryCode": "GB", - "geoCode": "E12000001", - "geoCodeType": "RGN/GOR" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm", - "additional_data": { - "locationLookup": [], - "recipientOrgInfos": [] - } - }, - { - "id": "360G-KJD-001231", - "title": "Grant award to Red Charity", - "description": "Towards the salary of an advice worker", - "currency": "GBP", - "amountAwarded": 10000, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "GB-CHC-1102541", - "name": "Red Charity" - } - ], - "beneficiaryLocation": [ - { - "name": "South West England", - "countryCode": "GB", - "geoCode": "E12000009", - "geoCodeType": "RGN/GOR" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm", - "additional_data": { - "locationLookup": [], - "recipientOrgInfos": [ - { - "dateRegistered": "" - } - ] - } - }, - { - "id": "360G-KJD-001232", - "title": "Grant award to Green House Charity", - "description": "Towards the purchase of a new minibus", - "currency": "GBP", - "amountAwarded": 3500, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "GB-SC-SC065843", - "name": "Green House Charity" - } - ], - "beneficiaryLocation": [ - { - "name": "Scotland", - "countryCode": "GB", - "geoCode": "S92000003 ", - "geoCodeType": "CTRY" - }, - { - "name": "Northern Ireland", - "countryCode": "GB", - "geoCode": "N92000002", - "geoCodeType": "CTRY" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm" - }, - { - "id": "360G-KJD-001233", - "title": "Grant award to Purple Community Group", - "description": "Towards the purchase of IT equipment", - "currency": "GBP", - "amountAwarded": 2000, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "GB-REV-XN65729", - "name": "Purple Community Group" - } - ], - "beneficiaryLocation": [ - { - "name": "Northern Ireland", - "countryCode": "GB", - "geoCode": "N92000002", - "geoCodeType": "CTRY" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm" - }, - { - "id": "360G-KJD-001234", - "title": "Grant award to Yellow Day Centre", - "description": "Towards the core costs of the centre", - "currency": "GBP", - "amountAwarded": 4500, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "GB-COH-08435647", - "name": "Yellow Day Centre" - } - ], - "beneficiaryLocation": [ - { - "name": "London", - "countryCode": "GB", - "geoCode": "E12000007", - "geoCodeType": "RGN/GOR" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm" - }, - { - "id": "360G-KJD-001235", - "title": "Grant award to Orange Gardens", - "description": "Towards the rebuilding of the historic orangery", - "currency": "GBP", - "amountAwarded": 15000, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "GB-COH-07345264", - "name": "Orange Gardens" - } - ], - "beneficiaryLocation": [ - { - "name": "Wales", - "countryCode": "GB", - "geoCode": "W92000004", - "geoCodeType": "CTRY" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm" - }, - { - "id": "360G-KJD-001236", - "title": "Grant award to Turquiose Foundation", - "description": "Towards the redevelopment of the website", - "currency": "GBP", - "amountAwarded": 1500, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "GB-CHC-1103425", - "name": "Turquiose Foundation" - } - ], - "beneficiaryLocation": [ - { - "name": "Yorkshire and The Humber", - "countryCode": "GB", - "geoCode": "E12000003", - "geoCodeType": "RGN/GOR" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm" - }, - { - "id": "360G-KJD-001237", - "title": "Grant award to Pink Playing Field", - "description": "Towards the maintenance of the field", - "currency": "GBP", - "amountAwarded": 2500, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "360G-KJD-ORG:Pink_Playing_Field", - "name": "Pink Playing Field" - } - ], - "beneficiaryLocation": [ - { - "name": "East Midlands", - "countryCode": "GB", - "geoCode": "E12000004", - "geoCodeType": "RGN/GOR" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm" - }, - { - "id": "360G-KJD-001238", - "title": "Grant award to Maroon Gallery", - "description": "Towards the annual art exhibition at the Maroon Gallery", - "currency": "GBP", - "amountAwarded": 7500, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "GB-COH-07564986", - "name": "Maroon Gallery" - } - ], - "beneficiaryLocation": [ - { - "name": "East Midlands", - "countryCode": "GB", - "geoCode": "E12000004", - "geoCodeType": "RGN/GOR" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm" - }, - { - "id": "360G-KJD-001239", - "title": "Grant award to Grey Scout Group", - "description": "Towards the roof repairs for the scout hut", - "currency": "GBP", - "amountAwarded": 8250, - "awardDate": "2017-12-08T00:00:00+00:00", - "recipientOrganization": [ - { - "id": "360G-KJD-ORG:Grey_Scout_Group", - "name": "Grey Scout Group" - } - ], - "beneficiaryLocation": [ - { - "name": "North West England", - "countryCode": "GB", - "geoCode": "E12000002", - "geoCodeType": "RGN/GOR" - } - ], - "fundingOrganization": [ - { - "id": "GB-CHC-301077", - "name": "K J D Foundation" - } - ], - "dateModified": "2017-12-22T00:00:00+00:00", - "dataSource": "http://www.example.org/grants.htm" - } - ] -} diff --git a/tests/sample-data/ExampleTrust-grants-fixed.xlsx b/tests/sample-data/ExampleTrust-grants-fixed.xlsx deleted file mode 100644 index ce1f6c13084430f679d241b726f196285cf4c469..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11173 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 diff --git a/tests/sample-data/ExampleTrust-grants-metadata.xlsx b/tests/sample-data/ExampleTrust-grants-metadata.xlsx deleted file mode 100644 index 22139a39f5130c93423f21a144d2a3f0f48f9d8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10308 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 j{8{n;S)9?&X#FqqjiL" diff --git a/tests/test_from_url.py b/tests/test_from_url.py deleted file mode 100644 index 8e91a6c..0000000 --- a/tests/test_from_url.py +++ /dev/null @@ -1,68 +0,0 @@ -import os - -from flask import request -import pytest -import requests_mock - - -@pytest.fixture -def m(): - urls = [ - ( - r"sample-data/ExampleTrust-grants-fixed.json", - "https://grantnav.threesixtygiving.org/grants/grants.json", - "application/json", - ), - ( - r"sample-data/ExampleTrust-grants-fixed.csv", - "https://grantnav.threesixtygiving.org/grants/grants.csv", - "text/csv", - ), - ( - r"sample-data/ExampleTrust-grants-broken.csv", - "https://grantnav.threesixtygiving.org/grants/broken-grants.csv", - "text/csv", - ), - ( - r"sample-data/360-giving-package-schema.json", - "https://raw.githubusercontent.com/ThreeSixtyGiving/standard/master/schema/360-giving-package-schema.json", - "application/json", - ), - ( - r"sample-data/360-giving-schema.json", - "https://raw.githubusercontent.com/ThreeSixtyGiving/standard/master/schema/360-giving-schema.json", - "application/json", - ), - ] - - m = requests_mock.Mocker() - thisdir = os.path.dirname(os.path.realpath(__file__)) - for i in urls: - with open(os.path.join(thisdir, i[0]), "rb") as f_: - m.get(i[1], content=f_.read(), headers={"Content-Type": i[2]}) - m.head(i[1], headers={"Content-Type": i[2]}) - - m.start() - return m - - -@pytest.mark.parametrize("url", [ - "https://grantnav.threesixtygiving.org/grants/grants.json", - "https://grantnav.threesixtygiving.org/grants/grants.csv", -]) -def test_fetch_from_url(m, client, url): - rv = client.get("/?url=" + url, follow_redirects=True) - assert rv.status_code == 200 - assert "/" in request.path - assert b'Uploaded dataset' in rv.data - assert b'Could not fetch from URL' not in rv.data - - -@pytest.mark.parametrize("url", [ - "https://raw.githubusercontent.com/ThreeSixtyGiving/standard/master/schema/360-giving-package-schema.json", -]) -def test_fetch_from_url_broken(m, client, url): - rv = client.get("/?url=" + url, follow_redirects=True) - assert rv.status_code == 200 - assert request.path == "/" - assert b'Could not fetch from URL' in rv.data diff --git a/tests/test_insights.py b/tests/test_insights.py deleted file mode 100644 index 1af76dc..0000000 --- a/tests/test_insights.py +++ /dev/null @@ -1,115 +0,0 @@ -import datetime -import os -import tempfile - -import pytest - -from insights import __version__, create_app -from insights.db import Grant, Publisher, SourceFile, db - - -def test_version(): - assert __version__ == "0.1.0" - - -@pytest.fixture -def test_app(): - app = create_app() - db_fd, db_path = tempfile.mkstemp() - app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///{}".format(db_path) - app.config["TESTING"] = True - - with app.app_context(): - db.create_all() - create_testdata_grants() - yield app - - os.close(db_fd) - os.unlink(db_path) - - -@pytest.fixture -def client(): - app = create_app() - db_fd, db_path = tempfile.mkstemp() - app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///{}".format(db_path) - app.config["TESTING"] = True - - with app.test_client() as client: - with app.app_context(): - db.create_all() - create_testdata_grants() - yield client - - os.close(db_fd) - os.unlink(db_path) - - -def create_testdata_grants(source_file_id="12345", publisher_prefix="360G-pub", source_file_modified=None, grant_dataset="main"): - if publisher_prefix is None: - publisher = None - else: - publisher = Publisher(prefix=publisher_prefix, name="Publisher") - db.session.merge(publisher) - source_file = SourceFile( - id=source_file_id, - title="Source file", - publisher=publisher, - ) - if source_file_modified: - source_file.modified = source_file_modified - db.session.merge(source_file) - grant_ids = [] - for i in range(0, 10): - g = Grant( - dataset=grant_dataset, - grant_id=f"testdata_{i}", - title=f"Testdata Grant {i}", - description="A testdata grant", - currency="GBP", - amountAwarded=100 * (i + 1), - awardDate=datetime.date(2020, (i % 12) + 1, (i % 28) + 1), - recipientOrganization_id=f"360G-testdata-{i}", - recipientOrganization_name=f"Testdata Recipient {i}", - fundingOrganization_id=f"360G-testdata-funder-{i % 3}", - fundingOrganization_name=f"Testdata Funder {i % 3}", - publisher=publisher, - source_file=source_file, - ) - g_merged = db.session.merge(g) - db.session.commit() - grant_ids.append(g_merged.id) - return grant_ids - - -def test_index(client): - rv = client.get("/") - assert rv.status_code == 200 - - -def test_about(client): - rv = client.get("/about") - assert rv.status_code == 200 - assert b"About 360Insights" in rv.data - - -def test_funder_dash(client): - rv = client.get("/funder/360G-testdata-funder-0") - assert rv.status_code == 200 - assert b"360G-testdata-funder-0" in rv.data - - -def test_funder_dash_404(client): - rv = client.get("/funder/360G-testdata-funder-not-found") - assert rv.status_code == 404 - - -def test_publisher_dash(client): - rv = client.get("/publisher/360G-pub") - assert rv.status_code == 200 - assert b"360G-pub" in rv.data - - -def test_publisher_dash_404(client): - rv = client.get("/publisher/360G-testdata-pub-not-found") - assert rv.status_code == 404 diff --git a/tests/test_utils.py b/tests/test_utils.py deleted file mode 100644 index 6dc5970..0000000 --- a/tests/test_utils.py +++ /dev/null @@ -1,130 +0,0 @@ -from insights.utils import ( - charity_number_to_org_id, - format_currency, - get_org_schema, - get_unique_list, - list_to_string, - pluralize, - to_band, -) - - -def test_get_org_schema_not_str(): - a, b = get_org_schema(123) - assert a is None - assert b == 123 - - -def test_get_org_schema_360G(): - for i in ["360G-123", "360g-123", "360G-123-456", "GB-123"]: - a, b = get_org_schema(i) - assert a is None - assert b == i - - -def test_get_org_schema_valid(): - for i in [ - ("GB-CHC-12345", "GB-CHC", "12345"), - ("GB-CHC-12345-678", "GB-CHC", "12345-678"), - ]: - a, b = get_org_schema(i[0]) - assert a == i[1] - assert b == i[2] - - -def test_to_band(): - assert to_band(1, [0, 3, 5], ["0-3", "4-5"]) == "0-3" - assert to_band(None, [0, 3, 5], ["0-3", "4-5"]) is None - assert to_band(0, [0, 3, 5], ["0-3", "4-5"]) is None - assert to_band(0, [-1, 3, 5], ["0-3", "4-5"]) == "0-3" - assert to_band(3, [0, 3, 5], ["0-3", "4-5"]) == "0-3" - assert to_band(4, [0, 3, 5], ["0-3", "4-5"]) == "4-5" - assert to_band(5, [0, 3, 5], ["0-3", "4-5"]) == "4-5" - assert to_band(10, [0, 3, 5], ["0-3", "4-5"]) is None - - -def test_list_to_string(): - lists = [ - (["a"], "a", {}), - (["a", "b"], "a and b", {}), - (["a", "b", "c"], "a, b and c", {}), - (["a", "b", "c", "d"], "a, b, c and d", {}), - (["a", "b", "c and d", "e"], "a, b, c and d, and e", {}), - (["a", "b", "c", "d"], "a, b, c, and d", {"oxford_comma": True}), - (["a", "b", "c", "d"], "a, b, c and d", {"oxford_comma": False}), - (["a", "b", "c", "d"], "a; b; c and d", {"separator": "; "}), - ( - ["a", "b", "c", "d"], - ["a", ", ", "b", ", ", "c", " and ", "d"], - {"as_list": True}, - ), - ( - ["a", "b", "c", "d"], - ["a", ", ", "b", ", ", "c", ", ", " and ", "d"], - {"as_list": True, "oxford_comma": True}, - ), - ] - for l in lists: - assert l[1] == list_to_string(l[0], **l[2]) - - -def test_pluralize(): - plurals = [ - ["sheep", "sheep", "sheep"], - ["grant", "grant", "grants"], - ["recipient", "recipient", "recipients"], - ["funder", "funder", "funders"], - ] - - for p in plurals: - assert p[1] == pluralize(p[0], 1) - assert p[2] == pluralize(p[0], 2) - assert p[2] == pluralize(p[0], 200) - - -def test_unique_list(): - lists = [ - (["a", "b", "c"], ["a", "b", "c"]), - (["a", "b", "b"], ["a", "b"]), - (["a", "a", "b", "b"], ["a", "b"]), - (["a"], ["a"]), - ] - for l in lists: - assert l[1] == get_unique_list(l[0]) - - -def test_format_currency(): - currencies = [ - (10, ("£10", ""), {}), - (10000, ("£10.0", "thousand"), {}), - (10000000, ("£10.0", "million"), {}), - (10000000000, ("£10.0", "billion"), {}), - # without humanize - (10, ("£10", ""), {"humanize_": False}), - (10000, ("£10,000", ""), {"humanize_": False}), - (10000000, ("£10,000,000", ""), {"humanize_": False}), - (10000000000, ("£10,000,000,000", ""), {"humanize_": False}), - # with abbreviations - (10, ("£10", ""), {"abbreviate": True}), - (10000, ("£10.0", "k"), {"abbreviate": True}), - (10000000, ("£10.0", "M"), {"abbreviate": True}), - (10000000000, ("£10.0", "bn"), {"abbreviate": True}), - # other currencies - (10, ("US$10", ""), {"currency": "USD"}), - (10000, ("€10.0", "thousand"), {"currency": "EUR"}), - (10000000, ("AUS10.0", "million"), {"currency": "AUS"}), - (10000000000, ("CND10.0", "billion"), {"currency": "CND"}), - ] - for c in currencies: - assert c[1] == format_currency(c[0], **c[2]) - - -def test_charity_number_to_org_id(): - charity_numbers = [ - (123545, None), - ("123456", "GB-CHC-123456"), - ("SC123456", "GB-SC-SC123456"), - ("NIC123456", "GB-NIC-NIC123456"), - ] - for c in charity_numbers: - assert charity_number_to_org_id(c[0]) == c[1]