-
Notifications
You must be signed in to change notification settings - Fork 527
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/develop' into fix-talkback-read
- Loading branch information
Showing
11 changed files
with
358 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
scripts/src/java/org/oppia/android/scripts/wiki/BUILD.bazel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
""" | ||
Libraries corresponding to scripting tools that help with continuous integration workflows. | ||
""" | ||
|
||
load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library") | ||
|
||
kt_jvm_library( | ||
name = "wiki_table_of_contents_check_lib", | ||
testonly = True, | ||
srcs = [ | ||
"WikiTableOfContentsCheck.kt", | ||
], | ||
visibility = ["//scripts:oppia_script_binary_visibility"], | ||
deps = [ | ||
"//scripts/src/java/org/oppia/android/scripts/common:bazel_client", | ||
"//scripts/src/java/org/oppia/android/scripts/common:git_client", | ||
], | ||
) |
82 changes: 82 additions & 0 deletions
82
scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package org.oppia.android.scripts.wiki | ||
|
||
import java.io.File | ||
|
||
/** | ||
* Script for ensuring that the table of contents in each wiki page matches with its respective headers. | ||
* | ||
* Usage: | ||
* bazel run //scripts:wiki_table_of_contents_check -- <path_to_default_working_directory> | ||
* | ||
* Arguments: | ||
* - path_to_default_working_directory: The default working directory on the runner for steps, and the default location of repository. | ||
* | ||
* Example: | ||
* bazel run //scripts:wiki_table_of_contents_check -- $(pwd) | ||
*/ | ||
fun main(vararg args: String) { | ||
// Path to the repo's wiki. | ||
val wikiDirPath = "${args[0]}/wiki/" | ||
val wikiDir = File(wikiDirPath) | ||
|
||
// Check if the wiki directory exists. | ||
if (wikiDir.exists() && wikiDir.isDirectory) { | ||
processWikiDirectory(wikiDir) | ||
println("WIKI TABLE OF CONTENTS CHECK PASSED") | ||
} else { | ||
println("No contents found in the Wiki directory.") | ||
} | ||
} | ||
|
||
private fun processWikiDirectory(wikiDir: File) { | ||
wikiDir.listFiles()?.forEach { file -> | ||
checkTableOfContents(file) | ||
} | ||
} | ||
|
||
private fun checkTableOfContents(file: File) { | ||
val fileContents = file.readLines() | ||
val tocStartIdx = fileContents.indexOfFirst { | ||
it.contains(Regex("""##\s+Table\s+of\s+Contents""", RegexOption.IGNORE_CASE)) | ||
} | ||
if (tocStartIdx == -1) { | ||
return | ||
} | ||
|
||
// Skipping the blank line after the ## Table of Contents | ||
val tocEndIdx = fileContents.subList(tocStartIdx + 2, fileContents.size).indexOfFirst { | ||
it.startsWith("#") | ||
}.takeIf { it != -1 } | ||
?: error("Wiki doesn't contain headers referenced in Table of Contents.") | ||
|
||
val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + tocEndIdx + 1) | ||
|
||
for (line in tocSpecificLines) { | ||
if (line.trimStart().startsWith("- [") && !line.contains("https://")) { | ||
validateTableOfContents(file, line) | ||
} | ||
} | ||
} | ||
|
||
private fun validateTableOfContents(file: File, line: String) { | ||
val titleRegex = "\\[(.*?)\\]".toRegex() | ||
val title = titleRegex.find(line)?.groupValues?.get(1)?.replace('-', ' ') | ||
?.replace(Regex("[?&./:’'*!,(){}\\[\\]+]"), "") | ||
?.trim() | ||
|
||
val linkRegex = "\\(#(.*?)\\)".toRegex() | ||
val link = linkRegex.find(line)?.groupValues?.get(1)?.removePrefix("#")?.replace('-', ' ') | ||
?.replace(Regex("[?&./:’'*!,(){}\\[\\]+]"), "") | ||
?.trim() | ||
|
||
// Checks if the table of content title matches with the header link text. | ||
val matches = title.equals(link, ignoreCase = true) | ||
if (!matches) { | ||
error( | ||
"\nWIKI TABLE OF CONTENTS CHECK FAILED" + | ||
"\nMismatch of Table of Content with headers in the File: ${file.name}. " + | ||
"\nThe Title: '${titleRegex.find(line)?.groupValues?.get(1)}' " + | ||
"doesn't match with its corresponding Link: '${linkRegex.find(line)?.groupValues?.get(1)}'." | ||
) | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
scripts/src/javatests/org/oppia/android/scripts/wiki/BUILD.bazel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
""" | ||
Tests corresponding to wiki-related checks. | ||
""" | ||
|
||
load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") | ||
|
||
kt_jvm_test( | ||
name = "WikiTableOfContentsCheckTest", | ||
srcs = ["WikiTableOfContentsCheckTest.kt"], | ||
deps = [ | ||
"//scripts/src/java/org/oppia/android/scripts/wiki:wiki_table_of_contents_check_lib", | ||
"//testing:assertion_helpers", | ||
"//third_party:com_google_truth_truth", | ||
"//third_party:org_jetbrains_kotlin_kotlin-test-junit", | ||
], | ||
) |
190 changes: 190 additions & 0 deletions
190
scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
package org.oppia.android.scripts.wiki | ||
|
||
import com.google.common.truth.Truth.assertThat | ||
import org.junit.After | ||
import org.junit.Before | ||
import org.junit.Rule | ||
import org.junit.Test | ||
import org.junit.rules.TemporaryFolder | ||
import org.oppia.android.testing.assertThrows | ||
import java.io.ByteArrayOutputStream | ||
import java.io.PrintStream | ||
|
||
/** Tests for [WikiTableOfContentsCheck]. */ | ||
class WikiTableOfContentsCheckTest { | ||
private val outContent: ByteArrayOutputStream = ByteArrayOutputStream() | ||
private val originalOut: PrintStream = System.out | ||
private val WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR = "WIKI TABLE OF CONTENTS CHECK PASSED" | ||
private val WIKI_TOC_CHECK_FAILED_OUTPUT_INDICATOR = "WIKI TABLE OF CONTENTS CHECK FAILED" | ||
|
||
@field:[Rule JvmField] val tempFolder = TemporaryFolder() | ||
|
||
@Before | ||
fun setUp() { | ||
System.setOut(PrintStream(outContent)) | ||
} | ||
|
||
@After | ||
fun tearDown() { | ||
System.setOut(originalOut) | ||
} | ||
|
||
@Test | ||
fun testWikiTOCCheck_noWikiDirExists_printsNoContentFound() { | ||
runScript() | ||
assertThat(outContent.toString().trim()).isEqualTo("No contents found in the Wiki directory.") | ||
} | ||
|
||
@Test | ||
fun testWikiTOCCheck_noWikiDirectory_printsNoContentFound() { | ||
tempFolder.newFile("wiki") | ||
runScript() | ||
assertThat(outContent.toString().trim()).isEqualTo("No contents found in the Wiki directory.") | ||
} | ||
|
||
@Test | ||
fun testWikiTOCCheck_validWikiTOC_checkPass() { | ||
tempFolder.newFolder("wiki") | ||
val file = tempFolder.newFile("wiki/wiki.md") | ||
file.writeText( | ||
""" | ||
## Table of Contents | ||
- [Introduction](#introduction) | ||
- [Usage](#usage) | ||
## Introduction | ||
Content | ||
## Usage | ||
Content | ||
""".trimIndent() | ||
) | ||
|
||
runScript() | ||
|
||
assertThat(outContent.toString().trim()).contains(WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR) | ||
} | ||
|
||
@Test | ||
fun testWikiTOCCheck_missingWikiTOC_returnsNoTOCFound() { | ||
tempFolder.newFolder("wiki") | ||
val file = tempFolder.newFile("wiki/wiki.md") | ||
file.writeText( | ||
""" | ||
- [Introduction](#introduction) | ||
- [Usage](#usage) | ||
## Introduction | ||
Content | ||
## Usage | ||
Content | ||
""".trimIndent() | ||
) | ||
|
||
runScript() | ||
|
||
assertThat(outContent.toString().trim()).contains(WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR) | ||
} | ||
|
||
@Test | ||
fun testWikiTOCCheck_wikiTOCReference_noHeadersFound_throwsException() { | ||
tempFolder.newFolder("wiki") | ||
val file = tempFolder.newFile("wiki/wiki.md") | ||
file.writeText( | ||
""" | ||
## Table of Contents | ||
- [Introduction](#introductions) | ||
""".trimIndent() | ||
) | ||
|
||
val exception = assertThrows<IllegalStateException>() { | ||
runScript() | ||
} | ||
|
||
assertThat(exception).hasMessageThat().contains( | ||
"Wiki doesn't contain headers referenced in Table of Contents." | ||
) | ||
} | ||
|
||
@Test | ||
fun testWikiTOCCheck_mismatchWikiTOC_checkFail() { | ||
tempFolder.newFolder("wiki") | ||
val file = tempFolder.newFile("wiki/wiki.md") | ||
file.writeText( | ||
""" | ||
## Table of Contents | ||
- [Introduction](#introductions) | ||
- [Usage](#usage) | ||
## Introduction | ||
Content | ||
## Usage | ||
Content | ||
""".trimIndent() | ||
) | ||
|
||
val exception = assertThrows<IllegalStateException>() { | ||
runScript() | ||
} | ||
|
||
assertThat(exception).hasMessageThat().contains(WIKI_TOC_CHECK_FAILED_OUTPUT_INDICATOR) | ||
} | ||
|
||
@Test | ||
fun testWikiTOCCheck_validWikiTOCWithSeparator_checkPass() { | ||
tempFolder.newFolder("wiki") | ||
val file = tempFolder.newFile("wiki/wiki.md") | ||
file.writeText( | ||
""" | ||
## Table of Contents | ||
- [Introduction To Wiki](#introduction-to-wiki) | ||
- [Usage Wiki-Content](#usage-wiki-content) | ||
## Introduction | ||
Content | ||
## Usage | ||
Content | ||
""".trimIndent() | ||
) | ||
|
||
runScript() | ||
|
||
assertThat(outContent.toString().trim()).contains(WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR) | ||
} | ||
|
||
@Test | ||
fun testWikiTOCCheck_validWikiTOCWithSpecialCharacter_checkPass() { | ||
tempFolder.newFolder("wiki") | ||
val file = tempFolder.newFile("wiki/wiki.md") | ||
file.writeText( | ||
""" | ||
## Table of Contents | ||
- [Introduction](#introduction?) | ||
- [Usage?](#usage) | ||
## Introduction | ||
Content | ||
## Usage | ||
Content | ||
""".trimIndent() | ||
) | ||
|
||
runScript() | ||
|
||
assertThat(outContent.toString().trim()).contains(WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR) | ||
} | ||
|
||
private fun runScript() { | ||
main(tempFolder.root.absolutePath) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.