Skip to content

Commit 4691ba4

Browse files
committed
feat(tests): more coverage;
- Add more coverage for deleting resources and positions. - Added more to migraiton script.
1 parent 5584fc3 commit 4691ba4

File tree

2 files changed

+113
-5
lines changed

2 files changed

+113
-5
lines changed

ckan/migration/versions/109_e12e991f586b_create_res_position_constraint.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
44
Sets deleted resource positions to null.
55
6+
Sets active resource positions incase of duplicates and
7+
none zero based indices.
8+
69
Revision ID: e12e991f586b
710
Revises: f7b64c701a10
811
Create Date: 2026-02-10 18:26:31.122945
@@ -22,20 +25,34 @@ def upgrade():
2225
op.execute("""
2326
UPDATE resource SET position=null WHERE state='deleted';
2427
""")
25-
print('Set position=null for deleted resources.')
28+
29+
op.execute("""
30+
WITH numbered AS (
31+
SELECT
32+
id,
33+
package_id,
34+
position,
35+
ROW_NUMBER() OVER (
36+
PARTITION BY package_id
37+
ORDER BY position
38+
) - 1 AS new_position
39+
FROM resource WHERE state='active'
40+
)
41+
UPDATE resource
42+
SET position=numbered.new_position
43+
FROM numbered
44+
WHERE resource.id = numbered.id
45+
AND resource.position != numbered.new_position;
46+
""")
2647

2748
op.create_unique_constraint(
2849
constraint_name='con_package_resource_unique_position',
2950
table_name='resource', columns=['package_id', 'position'],
3051
deferrable=True, initially="DEFERRED")
31-
print('Created "con_package_resource_unique_position"'
32-
' constraint on resource table')
3352

3453

3554
def downgrade():
3655
op.drop_constraint(
3756
constraint_name='con_package_resource_unique_position',
3857
table_name='resource',
3958
type_='unique')
40-
print('Dropped "con_package_resource_unique_position"'
41-
' constraint from resource table')

ckan/tests/logic/action/test_delete.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,97 @@ def test_resource_delete(self):
3535
assert res_obj.state == "deleted"
3636
assert res_obj.position is None
3737

38+
def test_mass_auto_resource_delete(self):
39+
"""
40+
Patching/updating a dataset with a new list of resources
41+
should mark the old ones as deleted. All resources should get
42+
proper positions set.
43+
44+
Updating the dataset's resources again should purge the deleted resources.
45+
There has to be an actual change to said resources.
46+
"""
47+
dataset = factories.Dataset()
48+
for _i in range(0,6):
49+
factories.Resource(package_id=dataset['id'])
50+
51+
pkg = helpers.call_action("package_show", id=dataset['id'])
52+
assert len(pkg['resources']) == 6
53+
assert pkg['resources'][0]['position'] == 0
54+
assert pkg['resources'][1]['position'] == 1
55+
assert pkg['resources'][2]['position'] == 2
56+
assert pkg['resources'][3]['position'] == 3
57+
assert pkg['resources'][4]['position'] == 4
58+
assert pkg['resources'][5]['position'] == 5
59+
60+
# test single delete resource
61+
deleted_res_id = pkg['resources'][2]['id']
62+
helpers.call_action("resource_delete", id=deleted_res_id)
63+
pkg = helpers.call_action("package_show", id=dataset['id'])
64+
65+
assert len(pkg['resources']) == 5
66+
assert pkg['resources'][0]['position'] == 0
67+
assert pkg['resources'][1]['position'] == 1
68+
assert pkg['resources'][2]['position'] == 2
69+
assert pkg['resources'][3]['position'] == 3
70+
assert pkg['resources'][4]['position'] == 4
71+
for r in pkg['resources']:
72+
assert r['id'] != deleted_res_id
73+
74+
res = model.Resource.get(deleted_res_id)
75+
76+
assert res.id == deleted_res_id
77+
assert res.position is None
78+
79+
# test mass soft delete resources
80+
old_resource_ids = []
81+
for r in pkg['resources']:
82+
old_resource_ids.append(r['id'])
83+
84+
new_resource_list = []
85+
for _i in range(0,6):
86+
new_resource_list.append(
87+
factories.Resource(package_id=dataset['id']))
88+
pkg = helpers.call_action("package_patch", id=dataset['id'],
89+
resources=new_resource_list)
90+
91+
assert len(pkg['resources']) == 6
92+
assert pkg['resources'][0]['position'] == 0
93+
assert pkg['resources'][1]['position'] == 1
94+
assert pkg['resources'][2]['position'] == 2
95+
assert pkg['resources'][3]['position'] == 3
96+
assert pkg['resources'][4]['position'] == 4
97+
assert pkg['resources'][5]['position'] == 5
98+
99+
pkg = helpers.call_action("package_show", id=dataset['id'])
100+
101+
for r in pkg['resources']:
102+
assert r['id'] not in old_resource_ids
103+
104+
for rid in old_resource_ids:
105+
res = model.Resource.get(rid)
106+
assert res.state == 'deleted'
107+
assert res.position is None
108+
109+
# test mass purge/hard delete resources
110+
new_resource_list = []
111+
for _i in range(0,6):
112+
new_resource_list.append(
113+
factories.Resource(package_id=dataset['id']))
114+
pkg = helpers.call_action("package_patch", id=dataset['id'],
115+
resources=new_resource_list)
116+
117+
assert len(pkg['resources']) == 6
118+
assert pkg['resources'][0]['position'] == 0
119+
assert pkg['resources'][1]['position'] == 1
120+
assert pkg['resources'][2]['position'] == 2
121+
assert pkg['resources'][3]['position'] == 3
122+
assert pkg['resources'][4]['position'] == 4
123+
assert pkg['resources'][5]['position'] == 5
124+
125+
for rid in old_resource_ids:
126+
res = model.Resource.get(rid)
127+
assert res is None
128+
38129
def test_resource_delete_for_delete(self):
39130

40131
dataset = factories.Dataset()

0 commit comments

Comments
 (0)