Skip to content

Commit 46efc66

Browse files
committed
Move flask-based tests of providers manager to FAB provider tests
When we remove flask from airlfow those tests in providers manager fail, moving them to FAB which uses flask (and the features tested are only anyhow working when FAB provider is installed) should solve the issue.
1 parent 550b2a7 commit 46efc66

File tree

2 files changed

+161
-135
lines changed

2 files changed

+161
-135
lines changed

airflow-core/tests/unit/always/test_providers_manager.py

Lines changed: 0 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525
from unittest.mock import patch
2626

2727
import pytest
28-
from flask_appbuilder.fieldwidgets import BS3TextFieldWidget
29-
from flask_babel import lazy_gettext
30-
from wtforms import BooleanField, Field, StringField
3128

3229
from airflow.exceptions import AirflowOptionalProviderFeatureException
3330
from airflow.providers_manager import (
@@ -263,138 +260,6 @@ def test_connection_form_widgets(self):
263260
connections_form_widgets = list(provider_manager.connection_form_widgets.keys())
264261
assert len(connections_form_widgets) > 29
265262

266-
@pytest.mark.parametrize(
267-
"scenario",
268-
[
269-
"prefix",
270-
"no_prefix",
271-
"both_1",
272-
"both_2",
273-
],
274-
)
275-
def test_connection_form__add_widgets_prefix_backcompat(self, scenario):
276-
"""
277-
When the field name is prefixed, it should be used as is.
278-
When not prefixed, we should add the prefix
279-
When there's a collision, the one that appears first in the list will be used.
280-
"""
281-
282-
class MyHook:
283-
conn_type = "test"
284-
285-
provider_manager = ProvidersManager()
286-
widget_field = StringField(lazy_gettext("My Param"), widget=BS3TextFieldWidget())
287-
dummy_field = BooleanField(label=lazy_gettext("Dummy param"), description="dummy")
288-
widgets: dict[str, Field] = {}
289-
if scenario == "prefix":
290-
widgets["extra__test__my_param"] = widget_field
291-
elif scenario == "no_prefix":
292-
widgets["my_param"] = widget_field
293-
elif scenario == "both_1":
294-
widgets["my_param"] = widget_field
295-
widgets["extra__test__my_param"] = dummy_field
296-
elif scenario == "both_2":
297-
widgets["extra__test__my_param"] = widget_field
298-
widgets["my_param"] = dummy_field
299-
else:
300-
raise ValueError("unexpected")
301-
302-
provider_manager._add_widgets(
303-
package_name="abc",
304-
hook_class=MyHook,
305-
widgets=widgets,
306-
)
307-
assert provider_manager.connection_form_widgets["extra__test__my_param"].field == widget_field
308-
309-
def test_connection_field_behaviors_placeholders_prefix(self):
310-
class MyHook:
311-
conn_type = "test"
312-
313-
@classmethod
314-
def get_ui_field_behaviour(cls):
315-
return {
316-
"hidden_fields": ["host", "schema"],
317-
"relabeling": {},
318-
"placeholders": {"abc": "hi", "extra__anything": "n/a", "password": "blah"},
319-
}
320-
321-
provider_manager = ProvidersManager()
322-
provider_manager._add_customized_fields(
323-
package_name="abc",
324-
hook_class=MyHook,
325-
customized_fields=MyHook.get_ui_field_behaviour(),
326-
)
327-
expected = {
328-
"extra__test__abc": "hi", # prefix should be added, since `abc` is not reserved
329-
"extra__anything": "n/a", # no change since starts with extra
330-
"password": "blah", # no change since it's a conn attr
331-
}
332-
assert provider_manager.field_behaviours["test"]["placeholders"] == expected
333-
334-
def test_connection_form_widgets_fields_order(self):
335-
"""Check that order of connection for widgets preserved by original Hook order."""
336-
test_conn_type = "test"
337-
field_prefix = f"extra__{test_conn_type}__"
338-
field_names = ("yyy_param", "aaa_param", "000_param", "foo", "bar", "spam", "egg")
339-
340-
expected_field_names_order = tuple(f"{field_prefix}{f}" for f in field_names)
341-
342-
class TestHook:
343-
conn_type = test_conn_type
344-
345-
provider_manager = ProvidersManager()
346-
provider_manager._connection_form_widgets = {}
347-
provider_manager._add_widgets(
348-
package_name="mock",
349-
hook_class=TestHook,
350-
widgets={f: BooleanField(lazy_gettext("Dummy param")) for f in expected_field_names_order},
351-
)
352-
actual_field_names_order = tuple(
353-
key for key in provider_manager.connection_form_widgets.keys() if key.startswith(field_prefix)
354-
)
355-
assert actual_field_names_order == expected_field_names_order, "Not keeping original fields order"
356-
357-
def test_connection_form_widgets_fields_order_multiple_hooks(self):
358-
"""
359-
Check that order of connection for widgets preserved by original Hooks order.
360-
Even if different hooks specified field with the same connection type.
361-
"""
362-
test_conn_type = "test"
363-
field_prefix = f"extra__{test_conn_type}__"
364-
field_names_hook_1 = ("foo", "bar", "spam", "egg")
365-
field_names_hook_2 = ("yyy_param", "aaa_param", "000_param")
366-
367-
expected_field_names_order = tuple(
368-
f"{field_prefix}{f}" for f in [*field_names_hook_1, *field_names_hook_2]
369-
)
370-
371-
class TestHook1:
372-
conn_type = test_conn_type
373-
374-
class TestHook2:
375-
conn_type = "another"
376-
377-
provider_manager = ProvidersManager()
378-
provider_manager._connection_form_widgets = {}
379-
provider_manager._add_widgets(
380-
package_name="mock",
381-
hook_class=TestHook1,
382-
widgets={
383-
f"{field_prefix}{f}": BooleanField(lazy_gettext("Dummy param")) for f in field_names_hook_1
384-
},
385-
)
386-
provider_manager._add_widgets(
387-
package_name="another_mock",
388-
hook_class=TestHook2,
389-
widgets={
390-
f"{field_prefix}{f}": BooleanField(lazy_gettext("Dummy param")) for f in field_names_hook_2
391-
},
392-
)
393-
actual_field_names_order = tuple(
394-
key for key in provider_manager.connection_form_widgets.keys() if key.startswith(field_prefix)
395-
)
396-
assert actual_field_names_order == expected_field_names_order, "Not keeping original fields order"
397-
398263
def test_field_behaviours(self):
399264
provider_manager = ProvidersManager()
400265
connections_with_field_behaviours = list(provider_manager.field_behaviours.keys())
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
from __future__ import annotations
18+
19+
from typing import TYPE_CHECKING
20+
21+
import pytest
22+
from flask_appbuilder.fieldwidgets import BS3TextFieldWidget
23+
from flask_babel import lazy_gettext
24+
from wtforms.fields.simple import BooleanField, StringField
25+
26+
from airflow.providers_manager import ProvidersManager
27+
28+
if TYPE_CHECKING:
29+
from wtforms.fields.core import Field
30+
31+
32+
@pytest.mark.parametrize(
33+
"scenario",
34+
[
35+
"prefix",
36+
"no_prefix",
37+
"both_1",
38+
"both_2",
39+
],
40+
)
41+
def test_connection_form__add_widgets_prefix_backcompat(scenario, cleanup_providers_manager):
42+
"""
43+
When the field name is prefixed, it should be used as is.
44+
When not prefixed, we should add the prefix
45+
When there's a collision, the one that appears first in the list will be used.
46+
"""
47+
48+
class MyHook:
49+
conn_type = "test"
50+
51+
provider_manager = ProvidersManager()
52+
widget_field = StringField(lazy_gettext("My Param"), widget=BS3TextFieldWidget())
53+
dummy_field = BooleanField(label=lazy_gettext("Dummy param"), description="dummy")
54+
widgets: dict[str, Field] = {}
55+
if scenario == "prefix":
56+
widgets["extra__test__my_param"] = widget_field
57+
elif scenario == "no_prefix":
58+
widgets["my_param"] = widget_field
59+
elif scenario == "both_1":
60+
widgets["my_param"] = widget_field
61+
widgets["extra__test__my_param"] = dummy_field
62+
elif scenario == "both_2":
63+
widgets["extra__test__my_param"] = widget_field
64+
widgets["my_param"] = dummy_field
65+
else:
66+
raise ValueError("unexpected")
67+
68+
provider_manager._add_widgets(
69+
package_name="abc",
70+
hook_class=MyHook,
71+
widgets=widgets,
72+
)
73+
assert provider_manager.connection_form_widgets["extra__test__my_param"].field == widget_field
74+
75+
76+
def test_connection_field_behaviors_placeholders_prefix(cleanup_providers_manager):
77+
class MyHook:
78+
conn_type = "test"
79+
80+
@classmethod
81+
def get_ui_field_behaviour(cls):
82+
return {
83+
"hidden_fields": ["host", "schema"],
84+
"relabeling": {},
85+
"placeholders": {"abc": "hi", "extra__anything": "n/a", "password": "blah"},
86+
}
87+
88+
provider_manager = ProvidersManager()
89+
provider_manager._add_customized_fields(
90+
package_name="abc",
91+
hook_class=MyHook,
92+
customized_fields=MyHook.get_ui_field_behaviour(),
93+
)
94+
expected = {
95+
"extra__test__abc": "hi", # prefix should be added, since `abc` is not reserved
96+
"extra__anything": "n/a", # no change since starts with extra
97+
"password": "blah", # no change since it's a conn attr
98+
}
99+
assert provider_manager.field_behaviours["test"]["placeholders"] == expected
100+
101+
102+
def test_connection_form_widgets_fields_order(cleanup_providers_manager):
103+
"""Check that order of connection for widgets preserved by original Hook order."""
104+
test_conn_type = "test"
105+
field_prefix = f"extra__{test_conn_type}__"
106+
field_names = ("yyy_param", "aaa_param", "000_param", "foo", "bar", "spam", "egg")
107+
108+
expected_field_names_order = tuple(f"{field_prefix}{f}" for f in field_names)
109+
110+
class TestHook:
111+
conn_type = test_conn_type
112+
113+
provider_manager = ProvidersManager()
114+
provider_manager._connection_form_widgets = {}
115+
provider_manager._add_widgets(
116+
package_name="mock",
117+
hook_class=TestHook,
118+
widgets={f: BooleanField(lazy_gettext("Dummy param")) for f in expected_field_names_order},
119+
)
120+
actual_field_names_order = tuple(
121+
key for key in provider_manager.connection_form_widgets.keys() if key.startswith(field_prefix)
122+
)
123+
assert actual_field_names_order == expected_field_names_order, "Not keeping original fields order"
124+
125+
126+
def test_connection_form_widgets_fields_order_multiple_hooks(cleanup_providers_manager):
127+
"""
128+
Check that order of connection for widgets preserved by original Hooks order.
129+
Even if different hooks specified field with the same connection type.
130+
"""
131+
test_conn_type = "test"
132+
field_prefix = f"extra__{test_conn_type}__"
133+
field_names_hook_1 = ("foo", "bar", "spam", "egg")
134+
field_names_hook_2 = ("yyy_param", "aaa_param", "000_param")
135+
136+
expected_field_names_order = tuple(
137+
f"{field_prefix}{f}" for f in [*field_names_hook_1, *field_names_hook_2]
138+
)
139+
140+
class TestHook1:
141+
conn_type = test_conn_type
142+
143+
class TestHook2:
144+
conn_type = "another"
145+
146+
provider_manager = ProvidersManager()
147+
provider_manager._connection_form_widgets = {}
148+
provider_manager._add_widgets(
149+
package_name="mock",
150+
hook_class=TestHook1,
151+
widgets={f"{field_prefix}{f}": BooleanField(lazy_gettext("Dummy param")) for f in field_names_hook_1},
152+
)
153+
provider_manager._add_widgets(
154+
package_name="another_mock",
155+
hook_class=TestHook2,
156+
widgets={f"{field_prefix}{f}": BooleanField(lazy_gettext("Dummy param")) for f in field_names_hook_2},
157+
)
158+
actual_field_names_order = tuple(
159+
key for key in provider_manager.connection_form_widgets.keys() if key.startswith(field_prefix)
160+
)
161+
assert actual_field_names_order == expected_field_names_order, "Not keeping original fields order"

0 commit comments

Comments
 (0)