Skip to content

Forms: Add theming support #362

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 369 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
369 commits
Select commit Hold shift + click to select a range
7813e30
Merge branch 'v.next' into feature-branches/forms
Aug 4, 2023
86098e4
run test from json data, not from service data
Aug 4, 2023
5b1a68c
update to latest core build
Aug 4, 2023
59eac24
Merge pull request #86 from ArcGIS/sor10874/remove-creds-from-test
sorenoid Aug 7, 2023
e095665
FormTextField description focus fix (#87)
kaushikrw Aug 7, 2023
85b8b67
add data. avoid expression names
Aug 8, 2023
c41ade1
avoid expression names
Aug 8, 2023
a0845aa
Merge branch 'feature-branches/forms' into sor10874/consume-core
Aug 8, 2023
d4da255
Form content clipping fix (#89)
kaushikrw Aug 9, 2023
c871fa2
remove preview that con no longer be doen without public serializatio…
Aug 16, 2023
7587ed3
Merge pull request #90 from Esri/sor10874/consume-core
sorenoid Aug 16, 2023
ee5e56a
add some remembers. not sure how to remember a State instance on a st…
Aug 22, 2023
4a86784
add saver for DateTimePickerState
Aug 24, 2023
127fad8
add saver for DateTimePickerState
Aug 24, 2023
973277e
remove logging
Aug 24, 2023
fcc8076
date time fixes wip
Aug 25, 2023
006865b
date time calcs all working correctly
Aug 25, 2023
af81018
remove print statements
Aug 25, 2023
a03d34b
doc, remove more print statements
Aug 25, 2023
ae0a0b0
better doc
Aug 25, 2023
8aa500b
eol at eof
Aug 25, 2023
ce5fed7
update textfield tests to use core API
Aug 28, 2023
c97ecf1
remove excess remembrance. refactor a bit for PR feedback.
Aug 29, 2023
7254fc8
Merge pull request #105 from Esri/sor10874/remember-saveable
sorenoid Aug 29, 2023
3e1551c
naming changes
Sep 1, 2023
eb0cdba
Merge branch 'feature-branches/forms' into sor10874/date-time-fixes
Sep 1, 2023
1cef49b
Merge pull request #106 from Esri/sor10874/date-time-fixes
sorenoid Sep 1, 2023
7b7314b
eol at eof
Sep 1, 2023
bf06d02
Merge pull request #109 from Esri/sor10874/forms-tests-core-compliance
sorenoid Sep 1, 2023
512a305
work around lack of recompose of the yearremove input for remembering…
Sep 1, 2023
c075be2
remove input for remembering the date time picker state. add a call t…
Sep 1, 2023
fe2f7bc
Merge remote-tracking branch 'origin/sor10874/now-freeze-fix' into so…
Sep 1, 2023
695a78d
fix issue with DateTimePicker state saver
Sep 1, 2023
cb343d9
address basic issue of enabling the OK button in a way that abides th…
Sep 6, 2023
1e1a6e1
fix min and max comparisons
Sep 6, 2023
08feee1
Update DateTimePicker.kt (#113)
kaushikrw Sep 6, 2023
43e9d03
init copy
kaushikrw Sep 6, 2023
78ee2d6
fixed compilation errors
kaushikrw Sep 6, 2023
ed53847
Featureforms micro-app update to cache portalitems (#107)
kaushikrw Sep 7, 2023
3b83209
Merge branch 'feature-branches/forms' into sor10874/now-freeze-fix
Sep 7, 2023
44600e8
remove commented out code
Sep 7, 2023
14596ef
Merge pull request #114 from Esri/sor10874/now-freeze-fix
sorenoid Sep 7, 2023
2b54c41
Merge branch 'feature-branches/forms' into sor10874/datetime-min-max
Sep 7, 2023
8e2875c
pick up latest SDK with mutable elements in the FeatureForm
Sep 7, 2023
4338945
moved imports
kaushikrw Sep 7, 2023
3caf98e
Merge branch 'feature-branches/forms' into kaushik/forms/time-picker
kaushikrw Sep 7, 2023
43b5f84
fixed timepicker bugs
kaushikrw Sep 7, 2023
22a2d60
added copyright
kaushikrw Sep 8, 2023
05975b4
Merge branch 'v.next' into kaushik/v.next_merge_update
kaushikrw Sep 8, 2023
92c0276
Merge pull request #122 from Esri/kaushik/v.next_merge_feature_forms
kaushikrw Sep 8, 2023
97a0d5b
Merge pull request #118 from Esri/sor10874/consume-core-3
sorenoid Sep 11, 2023
e55c9ab
move TimePickerState into the PickerContent. Remove call to datePicke…
Sep 11, 2023
584659f
remove unused code
Sep 11, 2023
6fd9f65
fix up last commit -- from the wrong source on my machine!
Sep 12, 2023
0c003ae
Merge pull request #116 from Esri/sor10874/datetime-min-max
sorenoid Sep 12, 2023
2bc30e3
Merge pull request #120 from Esri/kaushik/forms/time-picker
kaushikrw Sep 12, 2023
9abab47
subtract the offset to represent fake picker UTC, don't add it
Sep 12, 2023
9d8b968
picker dates is utc plus offset (not minus!). get the date millis aft…
Sep 13, 2023
6cc7739
erge branch 'feature-branches/forms' into sor10874/small-today-fix
Sep 13, 2023
ec0f6eb
fix now freeze (#123)
kaushikrw Sep 17, 2023
30a91ee
remove call to set date picker set selection, no longer needed.
Sep 18, 2023
31dd076
Merge branch 'feature-branches/forms' into sor10874/small-today-fix
Sep 18, 2023
75869cc
remove double counting
Sep 18, 2023
1e355ad
Merge pull request #124 from Esri/sor10874/small-today-fix
sorenoid Sep 19, 2023
635626f
wip with included build
Sep 19, 2023
2d59732
value, editable, and required events working for text fields.
Sep 19, 2023
047e2d6
dontuse a coroutine use a LaunchedEffect
Sep 19, 2023
2ed66b6
respect isRequired in TextFields!
Sep 19, 2023
3574726
Merge branch 'sor10874/required-text' into sor10874/consume-event-api
Sep 20, 2023
f96ea8a
required events support
Sep 20, 2023
4081342
note
Sep 20, 2023
7fa51f0
doc
Sep 20, 2023
d3b6c30
Merge pull request #125 from Esri/sor10874/required-text
sorenoid Sep 20, 2023
94d4ee2
Merge branch 'feature-branches/forms' into sor10874/consume-event-api
Sep 20, 2023
7c66dbf
date time expression support
Sep 21, 2023
06023a8
doc
Sep 21, 2023
b99e13c
add circular progress indicator
Sep 22, 2023
5fd826d
state flow combine
Sep 26, 2023
8614e1a
only evaluate expressions based on user edits to text fields, not due…
Sep 27, 2023
6b77b4a
text form changes to support use of combine
Sep 28, 2023
8b8b915
date time form element input type changes to support use of combine
Sep 28, 2023
ead7725
date time form element input type changes to support use of combine
Sep 28, 2023
ff0d79e
rollback versioning changes
Sep 28, 2023
dfad7cb
roll back unrelated code change
Sep 28, 2023
0b68862
remove redundant statefulness
Sep 28, 2023
8c8d63c
Merge pull request #126 from Esri/sor10874/consume-event-api
sorenoid Sep 28, 2023
dd73610
follow up to events API changes
Sep 28, 2023
82fd3f7
Merge pull request #129 from Esri/sor10874/consume-events-api-follow-up
sorenoid Sep 28, 2023
b6b1a8f
Merge branch 'v.next' into feature-branches/forms
Sep 28, 2023
07f49db
Forms combo box implementation (#127)
kaushikrw Sep 28, 2023
3f1a31b
Merge branch 'v.next' into feature-branches/forms
Sep 29, 2023
49ba865
Merge branch 'feature-branches/forms' of github.com:Esri/arcgis-maps-…
Sep 29, 2023
bcbbbc2
fix conflict resolution error
Sep 29, 2023
4c68afb
numeric text field support.
Sep 29, 2023
c3b1f99
fix conflict resolution error.
Oct 3, 2023
19014d3
remember to evaluate expressions
Oct 3, 2023
e0c4467
Form field states remember saveable (#131)
kaushikrw Oct 4, 2023
b0c0964
Merge pull request #132 from Esri/sor10874/fix-text-field-tests-2
sorenoid Oct 4, 2023
0692775
Merge branch 'feature-branches/forms' into sor10874/numeric-text-field
Oct 4, 2023
ba1ec4d
add domain, fieldType to BaseFieldProperties.
Oct 4, 2023
c14e96e
tests for numeric text box
Oct 5, 2023
c5927d5
self review
Oct 5, 2023
54ce572
change identifyLayer to identifyLayers (#137)
kaushikrw Oct 5, 2023
88f45f1
move fieldType and domain down to FormTextFieldState. get range from …
Oct 6, 2023
5c8ecb3
just use number keyboard for integers so negative numbers can be type…
Oct 6, 2023
9f70126
revert settings.gradle changes
Oct 6, 2023
b171853
Forms combo box required validation (#134)
kaushikrw Oct 6, 2023
1a6847f
hoist up the fieldType so the TextField is just handed a keyboard type.
Oct 6, 2023
87dc6cb
migrated to use standardbottomsheet instead of a scaffold (#135)
kaushikrw Oct 6, 2023
a29094e
updated sdk build to 4019 (#139)
kaushikrw Oct 6, 2023
d171636
use numeric keyboard in ComboBoxDialog filter when fieldType is numeric.
Oct 6, 2023
2552a79
filter out layers without forms in results of identify
Oct 7, 2023
4bf387e
simplify logic
Oct 9, 2023
ac0139d
Merge pull request #140 from Esri/sor10874/allow-no-forms-layers
sorenoid Oct 9, 2023
ccb0e20
Forms: DateTimeFieldState refactor (#133)
kaushikrw Oct 10, 2023
1f59bed
switch input support
Oct 11, 2023
ffd1b06
Merge branch 'feature-branches/forms' into sor10874/numeric-text-field
Oct 11, 2023
4d4cbf3
address feedback
Oct 11, 2023
598d6ec
drop the first isFocused StateFlow emission in the FormTextFieldState…
Oct 11, 2023
70791c2
Merge branch 'feature-branches/forms' into sor10874/switch
Oct 11, 2023
b6096ed
fall back to combo when the initial value doesn't match the on or off…
Oct 12, 2023
08e12d5
self review
Oct 12, 2023
623bc3a
rewrite validation for FormTextFields
Oct 13, 2023
6732bab
Forms : Refactor `ComboBoxFieldState` into `CodedValueFieldState` (#146)
kaushikrw Oct 13, 2023
a59bd3f
Merge branch 'feature-branches/forms' into sor10874/switch
Oct 13, 2023
696103c
Forms : Updated `ComboboxField` to display `CodedValue.name` (#148)
kaushikrw Oct 13, 2023
6c0b2e6
SwitchFieldState inherits from CodedValueFieldState
Oct 14, 2023
df93289
support error validation state in FormTextFieldState.Saver, rememember
Oct 14, 2023
8d76a01
Merge branch 'feature-branches/forms' into sor10874/numeric-text-field
Oct 15, 2023
64191d8
Merge branch 'feature-branches/forms' into sor10874/numeric-text-field
Oct 16, 2023
792fc6d
clean up, add runtime checks, comments.
Oct 16, 2023
1e80b21
further isolate error messaging and validation
Oct 16, 2023
f3d4ded
updated basetextfield label overflow and added preview (#150)
kaushikrw Oct 16, 2023
55ac7e4
Forms : introduce `RadioButtonInput` (#149)
kaushikrw Oct 16, 2023
6aa6300
Merge pull request #138 from Esri/sor10874/numeric-text-field
sorenoid Oct 16, 2023
7182bf7
Merge branch 'feature-branches/forms' into sor10874/switch
Oct 16, 2023
af57f34
conflict resolution
Oct 16, 2023
4541f08
fix collateral merge build breaker
Oct 17, 2023
7efe789
present the latest emitted value for a text field, regardless of edit…
Oct 17, 2023
f2fdf2f
allow switch to change when text field is tapped. remember if the swi…
Oct 17, 2023
b943468
Merge pull request #151 from Esri/sor10874/fix-build
sorenoid Oct 17, 2023
124d482
provide the Switch through the trailingIcon of the OutlinedTextField
Oct 17, 2023
7e27f4e
Merge pull request #144 from Esri/sor10874/switch
sorenoid Oct 17, 2023
0f81216
remove unnecessary open modifier
Oct 19, 2023
d939055
add try-catch to featureFormDefinition check (#155)
kaushikrw Oct 19, 2023
b113776
Merge pull request #157 from Esri/sor10874/remove-unnecessary-modifier
sorenoid Oct 19, 2023
ef10f69
drop first emitted value from properties.value in favor of the initia…
Oct 19, 2023
64c508b
Merge pull request #152 from Esri/sor10874/disappearing-edits
sorenoid Oct 20, 2023
bc1f9d3
Forms : Fix orientation changes for Dialogs (#156)
kaushikrw Oct 20, 2023
27645f3
Forms: `DateTimeField` changes (#161)
kaushikrw Oct 24, 2023
1f57e73
optimized expr eval ui (#169)
kaushikrw Oct 26, 2023
f9a0269
`Forms`: DateTimePicker defaults (#168)
kaushikrw Oct 26, 2023
3cad435
Update MapScreen.kt (#171)
kaushikrw Oct 26, 2023
3723391
removed FormElement dependency from FieldElement (#175)
kaushikrw Oct 27, 2023
9935042
consume update value (#162)
sorenoid Oct 30, 2023
e2b3713
update to rtc 4043 (#180)
sorenoid Oct 31, 2023
a091a65
`Forms`: Group Elements Support (#179)
kaushikrw Oct 31, 2023
78ea6c3
optimized state creation (#181)
kaushikrw Oct 31, 2023
1d67e28
update to build 4046 (#185)
kaushikrw Nov 3, 2023
2e4827c
use datetime raw value (#184)
sorenoid Nov 3, 2023
532765c
novaluelabel selection fix (#188)
kaushikrw Nov 3, 2023
53b8b98
searchable items map list screen (#189)
sorenoid Nov 7, 2023
2c5962e
bump sdk to 4056 (#196)
sorenoid Nov 8, 2023
a140a78
Forms: DatePickerDialog scaling (#198)
kaushikrw Nov 8, 2023
5a2b9b1
fix ff tests (#201)
sorenoid Nov 15, 2023
f1786d9
`Forms`: Micro-app add enterprise login (#204)
kaushikrw Nov 16, 2023
2b22e23
`Forms` : Microapp SideSheet support (#207)
kaushikrw Nov 17, 2023
397f18b
make values focusable (and copyable) when not editable (#200)
sorenoid Nov 17, 2023
09200a6
Forms: Add ComboBox tests (#141)
kaushikrw Nov 17, 2023
6c1fb17
`Forms` : GroupElements fixes (#210)
kaushikrw Nov 28, 2023
36f5921
`Forms` microapp : Add network credential store (#215)
kaushikrw Nov 30, 2023
977ec5a
`Forms`: GroupElement tests (#214)
kaushikrw Nov 30, 2023
c5bc0b1
`forms:` extract commit transaction to microapp (#209)
sorenoid Nov 30, 2023
9fd203e
`Forms`: Microapp add login url recent history (#222)
kaushikrw Dec 5, 2023
58fa3cf
`Forms`: Combo Box Dialog sizing (#225)
kaushikrw Dec 8, 2023
900e2bf
Merge branch 'v.next' into feature-branches/forms
Dec 14, 2023
e63fccd
Merge branch 'feature-branches/forms' of github.com:Esri/arcgis-maps-…
Dec 14, 2023
b9ad05f
`Forms`: Microapp optimizations (#239)
kaushikrw Dec 19, 2023
622b4a5
`Forms`: Common base state (#252)
kaushikrw Jan 3, 2024
8b7cd8e
refactored and removed feature form state (#250)
kaushikrw Jan 3, 2024
ba35112
validation via the SDK (#267)
sorenoid Jan 4, 2024
82848cf
`Forms`: Refactored Dialog Mechanism (#254)
kaushikrw Jan 4, 2024
bbf2cba
`Forms`: Iterable collection of states (#263)
kaushikrw Jan 4, 2024
c719181
fix renamed method calls (#271)
kaushikrw Jan 4, 2024
7f4cbd4
fix test compilation errors (#273)
sorenoid Jan 8, 2024
8be233c
`Forms`: Refactor Validation (#276)
kaushikrw Jan 12, 2024
3acc178
`Forms`: Fix failing tests (#283)
kaushikrw Jan 12, 2024
e186020
`Forms:` date time UI tests (#277)
sorenoid Jan 16, 2024
d17f31a
`Forms`: Refactored state flow based Impl into compose state based (#…
kaushikrw Jan 17, 2024
6630879
`Forms` : Added discardEdits API and UI (#295)
kaushikrw Jan 19, 2024
6f8f0e0
`Forms`: Submit Form Validation (#292)
kaushikrw Jan 19, 2024
8bd59c5
bumping sdk to 4122 (#299)
sorenoid Jan 19, 2024
eb66812
`Forms`: Select Feature (#298)
kaushikrw Jan 19, 2024
5cb09a1
merge v next (#302)
sorenoid Jan 20, 2024
7fa32d0
fix up versions.
Jan 20, 2024
7bcd70c
make FormElementState internal (#304)
kaushikrw Jan 21, 2024
08d546d
`Forms`: Update readme (#305)
kaushikrw Jan 23, 2024
a51cf4d
`Forms` : Update disabled fields style (#308)
kaushikrw Jan 31, 2024
204ff9f
Merge branch 'v.next' into feature-branches/forms
Feb 6, 2024
14afde8
incorporate breaking API change GroupElement.formElements -> GroupEle…
sorenoid Feb 6, 2024
6dc53db
`Forms`: Attachments API (#313)
kaushikrw Feb 13, 2024
14f2b44
Update evaluation expression loading animation (#322)
kaushikrw Feb 15, 2024
d444e53
reverted to outlinedtextfield (#323)
kaushikrw Feb 15, 2024
ce93efa
`Forms` Fork date picker (#321)
kaushikrw Feb 16, 2024
988e7a5
attachment UI functional prototype (#317)
sorenoid Feb 16, 2024
95cd777
Add version to API ref (#314) (#328)
puneet-pdx Feb 16, 2024
94ce2f7
Merge branch 'v.next' into feature-branches/forms
Feb 17, 2024
ce44056
`Forms` : Consume latest sdk (#324)
kaushikrw Feb 21, 2024
13e9fde
feature form recomposition when a new Feature is selected (#326)
sorenoid Feb 21, 2024
b903a5e
remove experimental softwarekeyboardcontroller (#335)
kaushikrw Feb 21, 2024
0a88843
`Forms`: Consume `validationErrors` stateflow (#338)
kaushikrw Feb 26, 2024
609b640
pick up SDK 4159 (#340)
sorenoid Feb 26, 2024
6d12cd8
`Forms`: Add basic theming support (#339)
kaushikrw Feb 27, 2024
b8fa3de
updated tests and removed clear icon for combo fields (#342)
kaushikrw Feb 28, 2024
9799209
make Attachment prototypes internal for release. (#344)
sorenoid Feb 29, 2024
8185418
`Forms` : Read only fields re-design (#346)
kaushikrw Mar 4, 2024
8da283f
`Forms`: bump sdk to 4167 (#347)
kaushikrw Mar 5, 2024
9743100
`Forms` : Revert map state (#348)
kaushikrw Mar 5, 2024
2d05a47
`Forms` api backwards compatibility validation (#345)
sorenoid Mar 5, 2024
7c6ab07
create an internal subpackage containing all non public packages. (#350)
sorenoid Mar 6, 2024
e71a65b
replace clear button on required date time fields (#351)
sorenoid Mar 7, 2024
f8c9fef
Merge branch 'v.next' into feature-branches/forms
Mar 15, 2024
97cd35e
`Forms` : add radio and switch tests (#352)
kaushikrw Mar 16, 2024
2091552
remove old view model test from app project.
Mar 16, 2024
f821830
Merge remote-tracking branch 'origin/feature-branches/forms' into fea…
Mar 16, 2024
f6ec166
update since version of the public FeatureForm composable method.
Mar 16, 2024
94dee94
add copyrights
Mar 18, 2024
b04cd17
remove kapt from featureforms app
Mar 18, 2024
c605d98
move ksp plugin to end of list
Mar 18, 2024
fac9c0f
Create README.md
sorenoid Mar 18, 2024
0742971
Add files via upload
sorenoid Mar 18, 2024
7456eb7
Update README.md
sorenoid Mar 18, 2024
d7f69f3
provide public webmap which has forms
Mar 19, 2024
013bdc1
Merge remote-tracking branch 'origin/feature-branches/forms' into fea…
Mar 19, 2024
6cb93b7
Merge branch 'v.next' into feature-branches/forms
Mar 19, 2024
fdd1dde
added full support
kaushikrw Mar 19, 2024
2df5b4d
removed radiobuttondefaults
kaushikrw Mar 19, 2024
f791558
added initial doc
kaushikrw Mar 19, 2024
cf954f8
updated featureformtheme to be an object with compositionlocal
kaushikrw Mar 19, 2024
ae246df
fix wrong imports
kaushikrw Mar 19, 2024
e1bb347
Merge branch 'feature-branches/forms' into kaushik/forms/theming
kaushikrw Apr 10, 2024
c48612d
added full doc
kaushikrw Apr 11, 2024
1e92b70
add initial test design
kaushikrw Apr 12, 2024
922a045
added all theming tests
kaushikrw Apr 12, 2024
be01d9d
Update featureforms.api
kaushikrw Apr 12, 2024
a3d9835
fix typo
kaushikrw Apr 12, 2024
115c581
add since tags
kaushikrw Apr 15, 2024
60e857e
added missing doc
kaushikrw Apr 15, 2024
119a60e
updated design based on new standard
kaushikrw Apr 26, 2024
9c8db84
renamed group colors properties
kaushikrw Apr 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
269 changes: 268 additions & 1 deletion toolkit/featureforms/api/featureforms.api

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import androidx.compose.ui.test.assert
import androidx.compose.ui.test.onChildren
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle

fun SemanticsNodeInteraction.getAnnotatedTextString(): AnnotatedString {
val textList = fetchSemanticsNode().config.first {
Expand Down Expand Up @@ -59,6 +60,24 @@ private fun isOfColor(color: Color): SemanticsMatcher = SemanticsMatcher(
}
}

fun SemanticsNodeInteraction.assertTextStyle(
style: TextStyle
): SemanticsNodeInteraction = assert(isOfTextStyle(style))

private fun isOfTextStyle(style: TextStyle): SemanticsMatcher = SemanticsMatcher(
"${SemanticsProperties.Text.name} is of style '$style'"
) {
val textLayoutResults = mutableListOf<TextLayoutResult>()
it.config.getOrNull(SemanticsActions.GetTextLayoutResult)
?.action
?.invoke(textLayoutResults)
return@SemanticsMatcher if (textLayoutResults.isEmpty()) {
false
} else {
textLayoutResults.first().layoutInput.style == style
}
}

private fun SemanticsNodeInteractionCollection.onChildWithText(value: String, recurse: Boolean = false): SemanticsNodeInteraction? {
val count = fetchSemanticsNodes().count()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
/*
* Copyright 2024 Esri
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.arcgismaps.toolkit.featureforms

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performImeAction
import androidx.compose.ui.test.performTextInput
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import com.arcgismaps.ArcGISEnvironment
import com.arcgismaps.data.ArcGISFeature
import com.arcgismaps.data.QueryParameters
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.featureforms.FeatureForm
import com.arcgismaps.mapping.featureforms.FieldFormElement
import com.arcgismaps.mapping.featureforms.FormElement
import com.arcgismaps.mapping.featureforms.GroupFormElement
import com.arcgismaps.mapping.layers.FeatureLayer
import com.arcgismaps.toolkit.featureforms.theme.EditableTextFieldColors
import com.arcgismaps.toolkit.featureforms.theme.EditableTextFieldTypography
import com.arcgismaps.toolkit.featureforms.theme.FeatureFormColorScheme
import com.arcgismaps.toolkit.featureforms.theme.FeatureFormTypography
import com.arcgismaps.toolkit.featureforms.theme.GroupElementColors
import com.arcgismaps.toolkit.featureforms.theme.GroupElementTypography
import com.arcgismaps.toolkit.featureforms.theme.RadioButtonFieldColors
import com.arcgismaps.toolkit.featureforms.theme.RadioButtonFieldTypography
import com.arcgismaps.toolkit.featureforms.theme.ReadOnlyFieldColors
import com.arcgismaps.toolkit.featureforms.theme.ReadOnlyFieldTypography
import junit.framework.TestCase
import kotlinx.coroutines.test.runTest
import org.junit.BeforeClass
import org.junit.Rule
import org.junit.Test

class ThemingTests {

@get:Rule
val composeTestRule = createComposeRule()

private fun getFormElementWithLabel(label: String): FormElement {
return featureForm.elements.first {
it.label == label
}
}

/**
* Given a FeatureForm with a custom color scheme and typography for editable fields
* When the FeatureForm is displayed
* Then the custom color scheme and typography are applied to the editable form elements
*/
@Test
fun testEditableFieldTheming() {
var colorScheme: FeatureFormColorScheme
var typography: FeatureFormTypography
// create custom color scheme and typography and apply to the FeatureForm
composeTestRule.setContent {
colorScheme = FeatureFormColorScheme.createDefaults(
editableTextFieldColors = EditableTextFieldColors.createDefaults(
focusedTextColor = Color.Red
)
)
typography = FeatureFormTypography.createDefaults(
editableTextFieldTypography = EditableTextFieldTypography.createDefaults(
labelStyle = TextStyle(
fontWeight = FontWeight.ExtraBold,
color = Color.Green
)
)
)
FeatureForm(
featureForm = featureForm,
colorScheme = colorScheme,
typography = typography
)
}
val formElement = getFormElementWithLabel("Text Box") as FieldFormElement
val label = composeTestRule.onNodeWithText(formElement.label, useUnmergedTree = true)
label.assertIsDisplayed()
label.assertTextStyle(
TextStyle(
fontWeight = FontWeight.ExtraBold,
color = Color.Green
)
)
val text =
composeTestRule.onNodeWithText(formElement.formattedValue, useUnmergedTree = true)
text.assertIsDisplayed()
text.performClick()
text.assertTextColor(Color.Red)
}

/**
* Given a FeatureForm with a custom color scheme that includes placeholder colors
* When the FeatureForm is displayed and a form element is focused
* Then the custom placeholder colors are applied to the form elements based on focus state
*/
@Test
fun testPlaceHolderTransformation() {
var colorScheme: FeatureFormColorScheme
// create custom color scheme and typography and apply to the FeatureForm
composeTestRule.setContent {
colorScheme = FeatureFormColorScheme.createDefaults(
editableTextFieldColors = EditableTextFieldColors.createDefaults(
unfocusedPlaceholderColor = Color.White,
focusedPlaceholderColor = Color.Red,
unfocusedTextColor = Color.Black,
focusedTextColor = Color.Blue
)
)
FeatureForm(
featureForm = featureForm,
colorScheme = colorScheme
)
}
val formElement = getFormElementWithLabel("An empty field") as FieldFormElement
val field = composeTestRule.onNodeWithText(formElement.label)
val placeholder = composeTestRule.onNodeWithText(formElement.hint, useUnmergedTree = true)
placeholder.assertIsDisplayed()
// test unfocused placeholder color
placeholder.assertTextColor(Color.White)
field.performClick()
// test focused placeholder color
placeholder.assertTextColor(Color.Red)
field.performTextInput("test")
val text = composeTestRule.onNodeWithText("test", useUnmergedTree = true)
text.assertIsDisplayed()
// test focused text color
text.assertTextColor(Color.Blue)
field.performImeAction()
// test unfocused text color
text.assertTextColor(Color.Black)
}

/**
* Given a FeatureForm with a custom color scheme and typography for read only fields
* When the FeatureForm is displayed
* Then the custom color scheme and typography are applied to the read only form elements
*/
@Test
fun testReadOnlyFieldTheming() {
var colorScheme: FeatureFormColorScheme
var typography: FeatureFormTypography
composeTestRule.setContent {
colorScheme = FeatureFormColorScheme.createDefaults(
readOnlyFieldColors = ReadOnlyFieldColors.createDefaults(
textColor = Color.Green
)
)
typography = FeatureFormTypography.createDefaults(
readOnlyFieldTypography = ReadOnlyFieldTypography.createDefaults(
labelStyle = TextStyle(
fontWeight = FontWeight.ExtraBold,
color = Color.Red
)
)
)
FeatureForm(
featureForm = featureForm,
colorScheme = colorScheme,
typography = typography
)
}
val formElement = getFormElementWithLabel("Name") as FieldFormElement
val label = composeTestRule.onNodeWithText(formElement.label, useUnmergedTree = true)
label.assertIsDisplayed()
label.assertTextStyle(
TextStyle(
fontWeight = FontWeight.ExtraBold,
color = Color.Red
)
)
val text =
composeTestRule.onNodeWithText(formElement.formattedValue, useUnmergedTree = true)
text.assertIsDisplayed()
text.assertTextColor(Color.Green)
}

/**
* Given a FeatureForm with a custom color scheme and typography for radio button fields
* When the FeatureForm is displayed
* Then the custom color scheme and typography are applied to the radio button form elements
*/
@Test
fun testRadioButtonFieldTheming() {
var colorScheme: FeatureFormColorScheme
var typography: FeatureFormTypography
composeTestRule.setContent {
colorScheme = FeatureFormColorScheme.createDefaults(
radioButtonFieldColors = RadioButtonFieldColors.createDefaults(
textColor = Color.Green
)
)
typography = FeatureFormTypography.createDefaults(
radioButtonFieldTypography = RadioButtonFieldTypography.createDefaults(
labelStyle = TextStyle(
fontWeight = FontWeight.ExtraBold,
color = Color.Red
)
)
)
FeatureForm(
featureForm = featureForm,
colorScheme = colorScheme,
typography = typography
)
}
val formElement = getFormElementWithLabel("Radio Button") as FieldFormElement
val label = composeTestRule.onNodeWithText(formElement.label, useUnmergedTree = true)
label.assertIsDisplayed()
label.assertTextStyle(
TextStyle(
fontWeight = FontWeight.ExtraBold,
color = Color.Red
)
)
val text =
composeTestRule.onNodeWithText(formElement.formattedValue, useUnmergedTree = true)
text.assertIsDisplayed()
text.assertTextColor(Color.Green)
}

/**
* Given a FeatureForm with a custom color scheme and typography for group elements
* When the FeatureForm is displayed
* Then the custom color scheme and typography are applied to the group form elements
*/
@Test
fun testGroupElementTheming() {
var colorScheme: FeatureFormColorScheme
var typography: FeatureFormTypography
composeTestRule.setContent {
colorScheme = FeatureFormColorScheme.createDefaults(
groupElementColors = GroupElementColors.createDefaults(
supportingTextColor = Color.Green
)
)
typography = FeatureFormTypography.createDefaults(
groupElementTypography = GroupElementTypography.createDefaults(
labelStyle = TextStyle(
fontWeight = FontWeight.ExtraBold,
color = Color.Blue
)
)
)
FeatureForm(
featureForm = featureForm,
colorScheme = colorScheme,
typography = typography
)
}
val groupElement = getFormElementWithLabel("Group One") as GroupFormElement
val label = composeTestRule.onNodeWithText(groupElement.label, useUnmergedTree = true)
label.assertIsDisplayed()
label.assertTextStyle(
TextStyle(
fontWeight = FontWeight.ExtraBold,
color = Color.Blue
)
)
val supportingText = composeTestRule.onNodeWithText(groupElement.description, useUnmergedTree = true)
supportingText.assertIsDisplayed()
supportingText.assertTextColor(Color.Green)
}

companion object {
private lateinit var featureForm: FeatureForm

@BeforeClass
@JvmStatic
fun setupClass() = runTest {
ArcGISEnvironment.authenticationManager.arcGISAuthenticationChallengeHandler =
FeatureFormsTestChallengeHandler(
BuildConfig.webMapUser,
BuildConfig.webMapPassword
)
val map =
ArcGISMap("https://runtimecoretest.maps.arcgis.com/home/item.html?id=615e8fe546ef4d139fb9298515c2f40a")
map.load().onFailure { TestCase.fail("failed to load webmap with ${it.message}") }
val featureLayer = map.operationalLayers.first() as? FeatureLayer
featureLayer?.let { layer ->
layer.load().onFailure { TestCase.fail("failed to load layer with ${it.message}") }
val featureFormDefinition = layer.featureFormDefinition!!
val parameters = QueryParameters().also {
it.objectIds.add(1L)
it.maxFeatures = 1
}
layer.featureTable?.queryFeatures(parameters)?.onSuccess { featureQueryResult ->
val feature = featureQueryResult.find {
it is ArcGISFeature
} as? ArcGISFeature
if (feature == null) TestCase.fail("failed to fetch feature")
feature?.load()?.onFailure {
TestCase.fail("failed to load feature with ${it.message}")
}
featureForm = FeatureForm(feature!!, featureFormDefinition)
featureForm.evaluateExpressions()
}?.onFailure {
TestCase.fail("failed to query features on layer's featuretable with ${it.message}")
}
}
}
}
}
Loading