uk_bin_collection 0.146.2__py3-none-any.whl → 0.147.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,94 +24,90 @@
24
24
  attribution: '© OpenStreetMap contributors'
25
25
  }).addTo(map);
26
26
 
27
- // Helper to slugify wiki anchor
28
27
  function slugify(str) {
29
28
  return str.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
30
29
  }
31
30
 
32
- fetch('tests/input.json')
33
- .then(res => res.json())
34
- .then(integrationData => {
35
- console.log("🔍 Loaded integration data:", integrationData);
36
-
37
- const coveredLADs = new Set();
38
- const integrationByLAD24CD = {};
39
-
40
- for (const [moduleName, entry] of Object.entries(integrationData)) {
41
- const wikiName = entry.wiki_name || moduleName;
42
- const wikiUrl = `https://github.com/robbrad/UKBinCollectionData/wiki/Councils#${slugify(wikiName)}`;
43
-
44
- // Case 1: Direct LAD24CD
45
- if (entry.LAD24CD) {
46
- const code = entry.LAD24CD?.replace(/[^\x20-\x7E]/g, '').trim();
47
- if (code) {
48
- coveredLADs.add(code);
49
- integrationByLAD24CD[code] = { wiki_name: wikiName, url: wikiUrl };
50
- } else {
51
- console.warn("⚠️ Entry with bad LAD24CD:", moduleName, entry);
52
- }
31
+ Promise.all([
32
+ fetch('tests/input.json').then(res => res.json()),
33
+ fetch('../build/integration-test-results/test_results.json').then(res => res.json()).catch(() => ({}))
34
+ ])
35
+ .then(([integrationData, testResults]) => {
36
+ console.log("🔍 Loaded integration data:", integrationData);
37
+ console.log("🧪 Loaded test results:", testResults);
38
+
39
+ const coveredLADs = new Set();
40
+ const integrationByLAD24CD = {};
41
+ const testStatusByLAD24CD = {};
42
+
43
+ for (const [moduleName, entry] of Object.entries(integrationData)) {
44
+ const wikiName = entry.wiki_name || moduleName;
45
+ const wikiUrl = `https://github.com/robbrad/UKBinCollectionData/wiki/Councils#${slugify(wikiName)}`;
46
+ const normalizeKey = str => str.toLowerCase().replace(/[^a-z0-9]/g, '');
47
+
48
+ const testResult = testResults[normalizeKey(moduleName)] || null;
49
+
50
+ const addCode = (code) => {
51
+ const cleanCode = code?.replace(/[^\x20-\x7E]/g, '').trim();
52
+ if (!cleanCode) return;
53
+
54
+ coveredLADs.add(cleanCode);
55
+ if (!integrationByLAD24CD[cleanCode]) {
56
+ integrationByLAD24CD[cleanCode] = { wiki_name: wikiName, url: wikiUrl };
57
+ testStatusByLAD24CD[cleanCode] = testResult;
53
58
  }
59
+ };
54
60
 
55
- // Case 2: Shared modules with multiple LADs
56
- if (Array.isArray(entry.supported_councils_LAD24CD)) {
57
- for (const codeRaw of entry.supported_councils_LAD24CD) {
58
- const code = codeRaw?.replace(/[^\x20-\x7E]/g, '').trim();
59
- if (code) {
60
- coveredLADs.add(code);
61
- // Only overwrite if not already present (prefer specific match)
62
- if (!integrationByLAD24CD[code]) {
63
- integrationByLAD24CD[code] = { wiki_name: wikiName, url: wikiUrl };
64
- }
65
- }
66
- }
67
- }
61
+ if (entry.LAD24CD) addCode(entry.LAD24CD);
62
+ if (Array.isArray(entry.supported_councils_LAD24CD)) {
63
+ for (const code of entry.supported_councils_LAD24CD) addCode(code);
68
64
  }
65
+ }
66
+
67
+ return fetch('Local_Authority_Boundaries.geojson')
68
+ .then(res => res.json())
69
+ .then(geojson => {
70
+ L.geoJSON(geojson, {
71
+ style: feature => {
72
+ const code = feature.properties.LAD24CD?.trim();
73
+ const isCovered = coveredLADs.has(code);
74
+ const testResult = testStatusByLAD24CD[code];
75
+
76
+ let fillColor = 'red'; // default: not covered
77
+ if (isCovered) {
78
+ fillColor = (testResult === 'pass') ? 'green' :
79
+ (testResult === 'fail') ? 'orange' : 'green';
80
+ }
69
81
 
70
- console.log("📦 Final covered LADs:", [...coveredLADs]);
71
-
72
- return fetch('Local_Authority_Boundaries.geojson')
73
- .then(res => res.json())
74
- .then(geojson => {
75
- L.geoJSON(geojson, {
76
- style: feature => {
77
- const code = feature.properties.LAD24CD?.trim();
78
- const isCovered = coveredLADs.has(code);
79
- return {
80
- color: '#333',
81
- weight: 1,
82
- fillColor: isCovered ? 'green' : 'red',
83
- fillOpacity: 0.6
84
- };
85
- },
86
- onEachFeature: (feature, layer) => {
87
- const code = feature.properties.LAD24CD?.trim();
88
- const name = feature.properties.LAD24NM;
89
- const covered = coveredLADs.has(code);
90
-
91
- if (!code) console.warn("⚠️ Missing LAD24CD in GeoJSON feature:", feature);
92
- if (!covered && code) console.warn("❌ Not covered LAD:", code, name);
93
-
94
- if (covered && integrationByLAD24CD[code]) {
95
- const wiki = integrationByLAD24CD[code];
96
- layer.bindPopup(
97
- `<strong>${name}</strong><br>Status: ✅ Covered<br>` +
98
- `<a href="${wiki.url}" target="_blank">📘 ${wiki.wiki_name}</a>`
99
- );
100
- } else {
101
- layer.bindPopup(`<strong>${name}</strong><br>Status: ❌ Not Covered`);
102
- }
82
+ return {
83
+ color: '#333',
84
+ weight: 1,
85
+ fillColor,
86
+ fillOpacity: 0.6
87
+ };
88
+ },
89
+ onEachFeature: (feature, layer) => {
90
+ const code = feature.properties.LAD24CD?.trim();
91
+ const name = feature.properties.LAD24NM;
92
+ const isCovered = coveredLADs.has(code);
93
+ const testResult = testStatusByLAD24CD[code];
94
+ const wiki = integrationByLAD24CD[code];
95
+
96
+ if (!code) return;
97
+
98
+ if (isCovered && wiki) {
99
+ const status = (testResult === 'pass') ? '✅ Covered (Test Passed)' :
100
+ (testResult === 'fail') ? '🟠 Covered (Test Failed)' :
101
+ '✅ Covered (No test result)';
102
+ layer.bindPopup(`<strong>${name}</strong><br>Status: ${status}<br><a href="${wiki.url}" target="_blank">📘 ${wiki.wiki_name}</a>`);
103
+ } else {
104
+ layer.bindPopup(`<strong>${name}</strong><br>Status: ❌ Not Covered`);
103
105
  }
104
- }).addTo(map);
105
-
106
- // Debug missing LADs
107
- const missing = geojson.features
108
- .map(f => [f.properties.LAD24CD?.trim(), f.properties.LAD24NM])
109
- .filter(([code]) => !coveredLADs.has(code))
110
- .map(([code, name]) => `${code} - ${name}`);
111
- console.warn("🛠️ Missing LADs in input.json:", missing);
112
- });
113
- })
114
- .catch(err => console.error('❌ Error loading data:', err));
106
+ }
107
+ }).addTo(map);
108
+ });
109
+ })
110
+ .catch(err => console.error('❌ Error loading data:', err));
115
111
  </script>
116
112
  </body>
117
113
 
@@ -0,0 +1,46 @@
1
+ import sys
2
+ import json
3
+ import xml.etree.ElementTree as ET
4
+ from collections import defaultdict
5
+ import re
6
+
7
+ def extract_council_name(testname):
8
+ """
9
+ Extracts the council name from the test name.
10
+ E.g. "test_scenario_outline[BarnetCouncil]" => "barnetcouncil"
11
+ """
12
+ match = re.search(r'\[(.*?)\]', testname)
13
+ if match:
14
+ return match.group(1).strip().lower()
15
+ return None
16
+
17
+ def parse_junit_xml(path):
18
+ tree = ET.parse(path)
19
+ root = tree.getroot()
20
+
21
+ results = defaultdict(lambda: "pass")
22
+
23
+ for testcase in root.iter("testcase"):
24
+ testname = testcase.attrib.get("name", "")
25
+ council = extract_council_name(testname)
26
+ if not council:
27
+ continue
28
+
29
+ if testcase.find("failure") is not None or testcase.find("error") is not None:
30
+ results[council] = "fail"
31
+
32
+ return results
33
+
34
+ def main():
35
+ if len(sys.argv) != 2:
36
+ print("Usage: python generate_test_results.py <junit.xml path>")
37
+ sys.exit(1)
38
+
39
+ junit_path = sys.argv[1]
40
+ results = parse_junit_xml(junit_path)
41
+
42
+ print(json.dumps(results, indent=2))
43
+
44
+
45
+ if __name__ == "__main__":
46
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uk_bin_collection
3
- Version: 0.146.2
3
+ Version: 0.147.1
4
4
  Summary: Python Lib to collect UK Bin Data
5
5
  Author: Robert Bradley
6
6
  Author-email: robbrad182@gmail.com
@@ -9,7 +9,6 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.12
10
10
  Classifier: Programming Language :: Python :: 3.13
11
11
  Requires-Dist: bs4
12
- Requires-Dist: geopandas (>=1.0.1,<2.0.0)
13
12
  Requires-Dist: holidays
14
13
  Requires-Dist: icalevents (>=0.2.1,<0.3.0)
15
14
  Requires-Dist: lxml
@@ -362,6 +361,42 @@ All integration tests results are in [CodeCov](https://app.codecov.io/gh/robbrad
362
361
  ### Nightly Full Integration Test Reports:
363
362
  - [Nightly Council Test](https://app.codecov.io/gh/robbrad/UKBinCollectionData/tests/master)
364
363
 
364
+
365
+ 🗺️ View Test Coverage Map (in VS Code)
366
+ ---------------------------------------
367
+
368
+ You can generate integration test results and view the interactive UK council coverage map with traffic-light-style statuses for each council.
369
+
370
+ ### 🧪 Step 1: Run Integration Tests
371
+
372
+ Run: `make integration-tests`
373
+
374
+ This runs the full BDD test suite and outputs a `junit.xml` report to:
375
+
376
+ `build/test/integration-test-results/junit.xml`
377
+
378
+ ### 📊 Step 2: Generate Map Test Results JSON
379
+
380
+ Convert the JUnit XML output to a flat test result JSON: `make generate-test-map-test-results`
381
+
382
+ This creates: `build/integration-test-results/test_results.json`
383
+
384
+ This file is used by the map to color each council:
385
+
386
+ * ✅ Green: Test passed
387
+ * 🟠 Amber: Test failed
388
+ * ❌ Red: Not integrated
389
+
390
+ ### 🗺️ Step 3: Open the Map
391
+
392
+ Open the map viewer in VS Code:
393
+
394
+ 1. Right-click the `map.html` file in VSCode and choose **Show Preview**
395
+
396
+ 2. The map will open in your browser, showing real-time integration coverage and test results.
397
+
398
+ ![Test Results Map](test_results_map.png)
399
+
365
400
  ---
366
401
  ## Docker API Server
367
402
  We have created an API for this located under [uk_bin_collection_api_server](https://github.com/robbrad/UKBinCollectionData/uk_bin_collection_api_server)
@@ -1,11 +1,12 @@
1
1
  uk_bin_collection/Local_Authority_Boundaries.geojson,sha256=_j-hUiL0--t2ewd_s29-j7_AKRlhagRMmOhXyco-B6I,1175922
2
2
  uk_bin_collection/README.rst,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  uk_bin_collection/compare_lad_codes.py,sha256=BjXPzxYbbqyl2Pv9yPip0BVpyD3GOofwgWa-BQUecqM,2214
4
- uk_bin_collection/map.html,sha256=qKc4Lscv1eSIc0M3vDofzZf5w9_eslEYpz1-kK4tup0,4346
4
+ uk_bin_collection/map.html,sha256=1xqlWRc2g4poZwT9FVdsSAkXPmkZ3dmQeA_-ikbU9dg,4135
5
5
  uk_bin_collection/tests/check_selenium_url_in_input.json.py,sha256=lf-JT7vvaSfvgbrfOhzrhfSzJqL82WajlRqo1GqfcMM,7875
6
6
  uk_bin_collection/tests/council_feature_input_parity.py,sha256=DO6Mk4ImYgM5ZCZ-cutwz5RoYYWZRLYx2tr6zIs_9Rc,3843
7
7
  uk_bin_collection/tests/features/environment.py,sha256=VQZjJdJI_kZn08M0j5cUgvKT4k3iTw8icJge1DGOkoA,127
8
8
  uk_bin_collection/tests/features/validate_council_outputs.feature,sha256=SJK-Vc737hrf03tssxxbeg_JIvAH-ddB8f6gU1LTbuQ,251
9
+ uk_bin_collection/tests/generate_map_test_results.py,sha256=8KjfNWNd44eGhiQMDJejoVzTh9dckGHikZQfwJgNO3w,1141
9
10
  uk_bin_collection/tests/input.json,sha256=-EVTLbgBwk879YMbAHkIYC7svXffzlL8xOa8Tab8M7g,133327
10
11
  uk_bin_collection/tests/output.schema,sha256=ZwKQBwYyTDEM4G2hJwfLUVM-5v1vKRvRK9W9SS1sd18,1086
11
12
  uk_bin_collection/tests/step_defs/step_helpers/file_handler.py,sha256=Ygzi4V0S1MIHqbdstUlIqtRIwnynvhu4UtpweJ6-5N8,1474
@@ -333,8 +334,8 @@ uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bId
333
334
  uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=QD4v4xpsEE0QheR_fGaNOIRMc2FatcUfKkkhAhseyVU,1159
334
335
  uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
335
336
  uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=YvmHfZqanwrJ8ToGch34x-L-7yPe31nB_x77_Mgl_vo,4545
336
- uk_bin_collection-0.146.2.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
337
- uk_bin_collection-0.146.2.dist-info/METADATA,sha256=1F2N9JtI_FSX2IALiojB8bO-kjCn1N2tNyAAnKGuv6s,19900
338
- uk_bin_collection-0.146.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
339
- uk_bin_collection-0.146.2.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
340
- uk_bin_collection-0.146.2.dist-info/RECORD,,
337
+ uk_bin_collection-0.147.1.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
338
+ uk_bin_collection-0.147.1.dist-info/METADATA,sha256=QntejjqYdQDDinBpWj5Nhb6PD1_WLXkwH5IrZ0q66cQ,20914
339
+ uk_bin_collection-0.147.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
340
+ uk_bin_collection-0.147.1.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
341
+ uk_bin_collection-0.147.1.dist-info/RECORD,,