fix: sort credential fields by display_order before rendering#339
fix: sort credential fields by display_order before rendering#339emmettownsend wants to merge 3 commits into
Conversation
The Credentials component renders fields in the order returned by the API without sorting by display_order. When the API returns password before username (as observed with MX Bank), users see password first — a confusing UX. This sorts credentials by display_order so fields render in the intended sequence regardless of API response ordering.
14036db to
1adbc27
Compare
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR ensures credential fields render in display_order rather than relying on the API response order, and adds a regression test to lock the behavior in.
Changes:
- Sort credentials by
display_orderbefore building form schema/values, rendering fields, focusing errored inputs, and building the connect payload. - Add a test covering rendering order independence from API ordering.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| src/views/credentials/Credentials.js | Sort credentials by display_order and use the sorted list consistently across the component. |
| src/views/credentials/tests/Credentials-test.tsx | Add a regression test asserting credential render order respects display_order. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const sortedCredentials = [...credentials].sort( | ||
| (a, b) => (a.display_order ?? 0) - (b.display_order ?? 0), | ||
| ) |
There was a problem hiding this comment.
Good catch — changed the default to Infinity so credentials without display_order sort to the end. Skipped the index tie-breaker since this is a 2-field login form in practice.
| const sortedCredentials = [...credentials].sort( | ||
| (a, b) => (a.display_order ?? 0) - (b.display_order ?? 0), | ||
| ) |
There was a problem hiding this comment.
Sorting 2 items on each render is effectively free — adding useMemo here would be more code for no measurable benefit.
|
|
||
| useEffect(() => { | ||
| for (const field of credentials) { | ||
| for (const field of sortedCredentials) { |
There was a problem hiding this comment.
The original code had the same pattern — credentials was used in this effect without being in the dependency array. This change only swapped the variable name; the dependency array behaviour is pre-existing.
| @@ -258,7 +261,7 @@ export const Credentials = React.forwardRef( | |||
| }, [errors]) | |||
There was a problem hiding this comment.
Same as above — pre-existing dependency array pattern, not introduced by this change.
| const inputs = await screen.findAllByRole('textbox') | ||
| expect(inputs[0]).toHaveAccessibleName(/Username/i) |
There was a problem hiding this comment.
Agreed — updated the test to query fields by their accessible labels and assert relative DOM position instead of relying on array indexing.
…tions - Use Infinity instead of 0 for missing display_order so credentials without the field sort to the end rather than the top - Query test fields by accessible label and assert DOM order instead of relying on array indexing of all textbox roles
- Wrap sortedCredentials in useMemo to match codebase conventions - Format test file to stay within line length limits - Add test for credentials with missing display_order falling to end
|
@emmettownsend how are you using this package? |
|
Hi,
We don't use it directly.
A conversation is happening about using MX for one of our US products.
We have used int-api.mx.com and int-widgets.moneydesktop.com to create a
demo showing one way to integrate the service.
If you don't use that package in the code behind those endpoints, it won't
be relevant.
I would have raised a support request, but I don't think our company has a
contract in place yet.
Best
Emmet
*Emmet Townsend*, VP Engineering
Contact | +1.857.339.2192 (M)
Connect | LinkedIn <https://www.linkedin.com/in/emmettownsend>, WebID
<https://emmettownsend.inrupt.net/profile/card#me>
Explore | www.inrupt.com
…On Thu, 11 Jun 2026 at 18:08, wesrisenmay-mx ***@***.***> wrote:
*wesrisenmay-mx* left a comment (mxenabled/connect-widget#339)
<#339 (comment)>
@emmettownsend <https://github.com/emmettownsend> how are you using this
package?
—
Reply to this email directly, view it on GitHub
<#339?email_source=notifications&email_token=AN5EYKMUE7UUGFIY2PD3NHD47LRSJA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINRYGMYDKMBRG4Y2M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-4683050171>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AN5EYKLOFB4PQYLQOS5LQTT47LRSJAVCNFSNUABFKJSXA33TNF2G64TZHM4DGNZTGE4DKMBYHNEXG43VMU5TINRTGM3TKNBQG4Y2C5QC>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/AN5EYKKDL5OM5WKU7WNNRMT47LRSJA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINRYGMYDKMBRG4Y2M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y>
and Android
<https://github.com/notifications/mobile/android/AN5EYKOJYTW2PIJNUE3CH3T47LRSJA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINRYGMYDKMBRG4Y2M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
Download it today!
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
This e-mail, and any attachments thereto, is intended only for use by the
addressee(s) named herein and may contain legally privileged, confidential
and/or proprietary information. If you are not the intended recipient of
this e-mail (or the person responsible for delivering this document to the
intended recipient), please do not disseminate, distribute, print or copy
this e-mail, or any attachment thereto. If you have received this e-mail in
error, please respond to the individual sending the message, and
permanently delete the email.
|
|
@emmettownsend Could you give it another go? I believe this was a configuration problem on our MX Bank Institution within the int environment. |
All good now. Thanks. |
|
Fixed via configuration |
Summary
When connecting to MX Bank (test institution), the password field renders above the username field. This happens because the
Credentialscomponent renders fields in whatever order the API returns them, without sorting bydisplay_order.Changes
display_orderinCredentials.jsbefore rendering, building form schema, and building initial valuesdisplay_ordergracefully (defaults to 0)Credentialscomponent so bothCreateMemberFormandUpdateMemberFormbenefitdisplay_orderregardless of API response orderRoot cause
Credentials.jsusescredentials.map(...)directly for rendering (line 446),buildInitialValues(line 115),buildFormSchema(line 116), andattemptConnect(line 261) — all without sorting bydisplay_order. When the MX Platform API returns credentials with password before username in the array, the widget displays them in that order.Fix
All references to
credentialswithin the component now usesortedCredentials.Test plan
display_order