Skip to content

Conversation

@CodeWithSangeeta
Copy link

@CodeWithSangeeta CodeWithSangeeta commented Dec 4, 2025

Explanation

Fix #5915: Improve TalkBack reading for concept card links

This PR updates the accessibility content description for the
<oppia-noninteractive-skillreview> custom HTML tag.

Earlier, TalkBack skipped the concept card link values.
Now, TalkBack consistently reads:

“<skill_id> concept card”

This improves the screen-reader experience in:

  • Hint section
  • Solution section
  • Flashback solution section

What this fixes

TalkBack was not reading concept-card links correctly because the custom HTML tag did not provide a clear accessibility description.
This PR fixes the issue and makes the content accessible for learners using screen readers.

What was changed

Updated ConceptCardTagHandler.getContentDescription()
→ Now returns a clean, consistent description using only theskill_id.

Updated SolutionViewModel
→ Now uses CustomHtmlContentHandler.getContentDescription() together with ConceptCardTagHandler to ensure correct accessibility parsing across hint and solution screens.

Additional note

This PR also includes an auto-format update to scripts/assets/kdoc_validity_exemptions.textproto
generated automatically by ktlint. No functional changes were made.

Testing done

Tested TalkBack behavior in all places where concept-card links appear:

  • Hint section
  • Solution section
  • Flashback mode

TalkBack now reads the concept card link:

  • Exactly once
  • In the correct format
  • With the correct text

Ready for review

Screen recording demonstrating TalkBack reading concept card links correctly in all 3 places: 🔗https://drive.google.com/file/d/1y6pqNhccfw5rjqeOtr_VNsF78jvSTvPN/view?usp=sharing

Essential Checklist

  • The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • Any changes to scripts/assets files have their rationale included in the PR explanation.
  • The PR follows the style guide.
  • The PR does not contain any unnecessary code changes from Android Studio (reference).
  • The PR is made from a branch that's not called "develop" and is up-to-date with "develop".
  • The PR is assigned to the appropriate reviewers (reference).

@CodeWithSangeeta
Copy link
Author

I have signed the CLA.

@CodeWithSangeeta
Copy link
Author

Hi! This is my first PR.
The Oppiabot and other automated checks are failing on my PR.
I verified my changes and everything seems correct.
Could you please approve the workflows or rerun the failing checks when possible?
Thank you!

@adhiamboperes
Copy link
Contributor

Hi @CodeWithSangeeta, I checked your fauling CI checks and saw there are failing tests. Some for the code paths you changed have existing regression tests related to talkback/content descriptions, and the tests either need to be updated to have the latest content description, or help verify whether the fix is correct.

I clicked on the failing test shards and searched "failures", e.g.:
Screenshot 2025-12-06 at 02 20 47

The Wiki also has a section on static checks and understanding CI failures, FYI.

@CodeWithSangeeta
Copy link
Author

Thank you for explaining the failing tests and for rerunning the workflows.

I understand now that the failures are due to UI tests still expecting the old TalkBack content descriptions. I will update the failing test files to match the new content descriptions from my change.

Really appreciate your help and guidance!

@CodeWithSangeeta
Copy link
Author

Hi! I’ve updated both StateFragmentTest and ExplorationActivityTest to match the new TalkBack concept card text and pushed the fix. The CI checks should rerun automatically now. Thanks again for the guidance!

@CodeWithSangeeta
Copy link
Author

Hi @adhiamboperes ,just a gentle follow-up on this PR. I’ve updated the failing tests based on the earlier feedback and pushed the fixes. Please let me know if anything else is needed from my side. Thank you!

Copy link
Contributor

@adhiamboperes adhiamboperes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @CodeWithSangeeta!

You solution is definitely in the right direction, but I have left some comments. Please ping me incase you run into issues.

Comment on lines 72 to 75

/** Override default HTML parsing to include custom concept card tags when generating TalkBack-readable text for Solution and Flashback dialogs.
The previous implementation ignored custom tags, causing TalkBack to skip this fix ensures that TalkBack reads the concept card reference
exactly once and consistently.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reformat this KDoc so that the sentences are clearly seperated.

Comment on lines 55 to 58
/** Updated content description logic for accessibility.
TalkBack must read the skill ID in concept card links(e.g., “test_skill_id_1 concept card.”)
Previously only the visible text was read, causing TalkBack to skip concept card references in Hint, Solution, and Flashback flows.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is okay to remove this KDoc. Interface methods are typically documented inside the interface itself, rather than at the implementation site.

Comment on lines 302 to 303
exempted_file_path: "utility/src/main/java/org/oppia/android/util/parser/html/
ConceptCardTagHandler.kt"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert this change, it looks like an erronous formatting change.


onView(withId(R.id.solution_summary))
.perform(openClickableSpan("test_skill_id_1 concept card"))
.perform(openClickableSpan("Click on this test_skill_id_1 concept card.."))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the span content change always, or just when talkback is enabled? I believed it is for the latter scenario.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto the other modified tests.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks for flagging this @adhiamboperes
The intention was to improve TalkBack output, not change visible span text universally.
I’ll update the implementation so the visible span remains unchanged and only the contentDescription reflects the TalkBack-specific wording.
Please tell me what to do??

*/
fun createConceptCardLinkClickListener(): ConceptCardLinkClickListener {
return object : ConceptCardLinkClickListener {
return object : ConceptCardTagHandler.ConceptCardLinkClickListener {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear to me why this change was required. Please verify and maybe revert.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out. You’re right — this change isn’t required for the TalkBack fix. I’ve reverted it to avoid unnecessary refactoring and verified that the app builds, runs correctly, and the TalkBack behavior remains unchanged

@CodeWithSangeeta
Copy link
Author

Screenshot 2025-12-25 171544

Hii @adhiamboperes ,
I noticed the failure happens because the second answer ("1/4") is correct, so the app transitions to the success/confetti state.
However, the test continues to interact with question UI (concept card / hints), which no longer exists at that point.

Could you please confirm whether:

  • both submitted answers should be incorrect, or
  • the test should stop interacting with question UI after a correct answer?

@oppiabot
Copy link

oppiabot bot commented Jan 1, 2026

Hi @CodeWithSangeeta, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue.
If you are still working on this PR, please make a follow-up commit within 3 days (and submit it for review, if applicable). Please also let us know if you are stuck so we can help you!

@oppiabot oppiabot bot added the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Jan 1, 2026
@CodeWithSangeeta
Copy link
Author

Hi @adhiamboperes,

Quick update to keep this PR active. I’m currently investigating test failures where the flow moves to the success/confetti state after a correct answer, but some tests continue interacting with the previous question UI (concept card / hints).

I’m working on confirming the expected behavior and will follow up with a fix or proposal soon.
Thanks for your patience—still actively debugging the failing tests and validating the expected behavior.

@oppiabot oppiabot bot removed the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Jan 1, 2026
@oppiabot
Copy link

oppiabot bot commented Jan 8, 2026

Hi @CodeWithSangeeta, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue.
If you are still working on this PR, please make a follow-up commit within 3 days (and submit it for review, if applicable). Please also let us know if you are stuck so we can help you!

@oppiabot oppiabot bot added the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Jan 8, 2026
@oppiabot oppiabot bot closed this Jan 15, 2026
@CodeWithSangeeta
Copy link
Author

Hi @adhiamboperes,
Just noticed the PR was auto-closed by the stale bot while I was waiting for clarification on the failing tests. I’m still actively working on this and would be happy to reopen or follow a revised approach if this issue is still relevant.
Thanks for your guidance so far.

@adhiamboperes adhiamboperes reopened this Jan 16, 2026
@oppiabot oppiabot bot removed the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Jan 16, 2026
Copy link
Contributor

@adhiamboperes adhiamboperes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @CodeWithSangeeta! I have reviewed the PR and suggested fixes for the failing tests. PTAL.

This PR is cquite close to being merge ready.

val solutionBoxStrokeWidth: Int
val solutionBoxStrokeWidth: Int,
private val consoleLogger: ConsoleLogger

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the unneccessary newline.

Comment on lines 77 to 81
* The previous implementation ignored custom tags.
* This caused TalkBack to skip concept card references.
*
* This fix ensures that TalkBack reads the concept card reference exactly once
* and consistently.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this information to the PR body instead of the KDoc, mainly because it is not relevant to describing what the code does.

onView(withId(R.id.hints_and_solution_summary))
.inRoot(isDialog())
.perform(openClickableSpan("test_skill_id_1 concept card"))
.perform(openClickableSpan("Click on this test_skill_id_1 concept card.."))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test and the one below are failing due to the incorrect assertion. The clicksble span should contain the text in the textview, please see screeenshot.

Screenshot 2026-01-20 at 19 25 32

"Remember that two halves, when added together, make one whole." +
"\nClick on this test_skill_id_1 concept card."
"Remember that two halves, when added together, make one whole.\n" +
"Click on this test_skill_id_1 concept card.."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should only be one period at the end.


onView(withId(R.id.solution_summary))
.perform(openClickableSpan("test_skill_id_1 concept card"))
.perform(openClickableSpan("Click on this test_skill_id_1 concept card."))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 tests have the same issue as above. Please see the text portion of the stacktrace to see the corrected expected text and use it to update the test.

* and the associated skill ID to enable further action handling.
*/
fun createConceptCardLinkClickListener(): ConceptCardLinkClickListener {
// return object : ConceptCardTagHandler.ConceptCardLinkClickListener {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the commented out code.

text
val skillId = attributes.getJsonStringValue(CUSTOM_CONCEPT_CARD_SKILL_ID)
return if (!skillId.isNullOrBlank()) {
"$skillId concept card."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that the period here is causing the double periods to appear in the text?(as per tests above?)

Suggested change
"$skillId concept card."
"$skillId concept card"

@adhiamboperes
Copy link
Contributor

Hi @adhiamboperes,

Quick update to keep this PR active. I’m currently investigating test failures where the flow moves to the success/confetti state after a correct answer, but some tests continue interacting with the previous question UI (concept card / hints).

I’m working on confirming the expected behavior and will follow up with a fix or proposal soon. Thanks for your patience—still actively debugging the failing tests and validating the expected behavior.

I think this was a weird CI test flake that I noticed a few weeks back, but since I re-run the tests, you can see that only 4 tests are failng and are directly related to the PR.

@CodeWithSangeeta
Copy link
Author

Hi @adhiamboperes,
Thanks for the update.

I’ve followed the review suggestions so far (including addressing the punctuation issue and updating the related tests) and pushed the changes. I’ll keep an eye on the remaining failing tests and follow up if anything else comes up.

Thanks again for taking a look.

@CodeWithSangeeta
Copy link
Author

Hii, I’ve fixed the failing test cases and pushed the updates.
Could you please approve the pending workflows or re-run CI when you get a chance?

Thanks!

@CodeWithSangeeta
Copy link
Author

Hii, I’ve pushed fixes for the test failures. Could you please re-run the TalkBack CI checks? Thanks!

@CodeWithSangeeta
Copy link
Author

Hi, I’ve pushed commits to fix the latest TalkBack test failure.
The failure was due to strict string matching in ClickableSpan assertions, so I updated the tests to use containsString for stability.
Whenever you have time, could you please re-run the TalkBack CI checks? Thanks!

@manas-yu manas-yu enabled auto-merge (squash) January 26, 2026 04:30
@manas-yu manas-yu disabled auto-merge January 26, 2026 04:30
@CodeWithSangeeta
Copy link
Author

Hi @adhiamboperes,

I reverted my last change since it introduced a type mismatch and didn’t align with the runtime accessibility text.

I’m seeing repeated failures in StateFragmentTest and ExplorationActivityTest caused by newline differences in the accessibility contentDescription. I tried aligning the tests with the current output, but the expected formatting (single vs double newline before the concept card text) seems inconsistent across cases.

Could you please confirm the intended behavior for the newline/formatting before the concept card text? I’ll wait for confirmation before reapplying further changes.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: Talkback is not reading concept card link on Solution box

2 participants