From 13efcfa4e4b40972ab2d951790cb2eea71b44e6d Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 10 Apr 2024 23:51:08 +0530 Subject: [PATCH 01/24] Script to Check the Table of Contents in the Wiki and CI workflow --- .github/workflows/wiki.yml | 18 ++++ scripts/BUILD.bazel | 7 ++ .../oppia/android/scripts/wiki/BUILD.bazel | 18 ++++ .../scripts/wiki/WikiTableOfContentsCheck.kt | 93 +++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 scripts/src/java/org/oppia/android/scripts/wiki/BUILD.bazel create mode 100644 scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index f37031f61e9..66ab33d7ca3 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -10,6 +10,24 @@ on: gollum: jobs: + table_of_contents_check: + name: Wiki Check Table of Contents match Headers + runs-on: ubuntu-20.04 + env: + CACHE_DIRECTORY: ~/.bazel_cache + steps: + - uses: actions/checkout@v2 + + - name: Set up Bazel + uses: abhinavsingh/setup-bazel@v3 + with: + version: 4.0.0 + + - name: Wiki Check Table of Contents + id: wikichecktoc + run: | + bazel run //scripts:wiki_table_of_contents_check -- ${GITHUB_WORKSPACE} + wiki-deploy: runs-on: ${{ matrix.os }} strategy: diff --git a/scripts/BUILD.bazel b/scripts/BUILD.bazel index 01390e600e7..b404a09ef61 100644 --- a/scripts/BUILD.bazel +++ b/scripts/BUILD.bazel @@ -227,6 +227,13 @@ kt_jvm_binary( ], ) +kt_jvm_binary( + name = "wiki_table_of_contents_check", + testonly = True, + main_class = "org.oppia.android.scripts.wiki.WikiTableOfContentsCheckKt", + runtime_deps = ["//scripts/src/java/org/oppia/android/scripts/wiki:wiki_table_of_contents_check_lib"], +) + # Note that this is intentionally not test-only since it's used by the app build pipeline. Also, # this apparently needs to be a java_binary to set up runfiles correctly when executed within a # Starlark rule as a tool. diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/BUILD.bazel b/scripts/src/java/org/oppia/android/scripts/wiki/BUILD.bazel new file mode 100644 index 00000000000..6898d1b8c21 --- /dev/null +++ b/scripts/src/java/org/oppia/android/scripts/wiki/BUILD.bazel @@ -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", + ], +) diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt new file mode 100644 index 00000000000..eeadf710480 --- /dev/null +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -0,0 +1,93 @@ +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_sample -- + * + * 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_sample -- ${GITHUB_WORKSPACE} + */ +fun main(vararg args: String) { + // Path to the repo's wiki. + val githubWorkspace = "${args[0]}/wiki/" + val wikiDirectory = File(githubWorkspace) + + // Check if the wiki directory exists + if (wikiDirectory.exists() && wikiDirectory.isDirectory) { + processWikiDirectory(wikiDirectory) + } else { + println("No contents found in the Wiki directory.") + } +} + +/** + * Checks every file in the wiki repo + * + * @param wikiDirectory the default working directory + */ +fun processWikiDirectory(wikiDirectory: File) { + wikiDirectory.listFiles()?.forEach { file -> + processWikiFile(file) + } +} + +/** + * Processes the contents of a single wiki file to ensure the accuracy of the Table of Contents. + * + * @param file The wiki file to process. + */ +fun processWikiFile(file: File) { + var inTableOfContents = false + var skipBlankLine = false + + file.forEachLine { line -> + when { + // Checking for Table of Contents section + line.trim() == "## Table of Contents" -> { + inTableOfContents = true + skipBlankLine = true + } + // Checking to skip the blank line immediately after the ## Table of Contents + skipBlankLine && line.isBlank() -> skipBlankLine = false + // Validating the contents in the Table of Content + inTableOfContents && line.trimStart().startsWith("- [") && !line.contains("https://") -> { + validateTableOfContents(file, line) + } + // Checking for end of Table of Contents section + inTableOfContents && line.isBlank() -> inTableOfContents = false + } + } +} + +/** + * Validates the accuracy of a Table of Contents entry in a wiki file. + * + * @param file The wiki file being validated. + * @param line The line containing the Table of Contents entry. + */ +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("[?&./:’'*!,(){}\\[\\]+]"), "") + ?.replace("confetti_ball", "")?.trim() + + // Checks if the table of content title matches with the header link text + val matches = title.equals(link, ignoreCase = true) + if (!matches) { + throw Exception("\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)}'.") + } +} From d3795b3c1828fc5abaa27dc1b9ef5fd2c09a5f50 Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 11 Apr 2024 00:54:12 +0530 Subject: [PATCH 02/24] Fix Lint Tests by adding new lines after and before ( and ) --- .../oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index eeadf710480..f556ec0da05 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -86,8 +86,10 @@ fun validateTableOfContents(file: File, line: String) { // Checks if the table of content title matches with the header link text val matches = title.equals(link, ignoreCase = true) if (!matches) { - throw Exception("\nMismatch of Table of Content with headers in the File: ${file.name}. " + + throw Exception( + "\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)}'.") + "doesn't match with its corresponding Link: '${linkRegex.find(line)?.groupValues?.get(1)}'." + ) } } From 1840f6092efa4ec21b371e0083d32b88c41a3633 Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 11 Apr 2024 00:59:51 +0530 Subject: [PATCH 03/24] Fix Lint Tests by properly indenting the error messages --- .../oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index f556ec0da05..fd2412fb082 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -88,8 +88,8 @@ fun validateTableOfContents(file: File, line: String) { if (!matches) { throw Exception( "\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)}'." + "\nThe Title: '${titleRegex.find(line)?.groupValues?.get(1)}' " + + "doesn't match with its corresponding Link: '${linkRegex.find(line)?.groupValues?.get(1)}'." ) } } From d113747e709ac4755adaedaba40f8d574a8ba356 Mon Sep 17 00:00:00 2001 From: Rd Date: Tue, 30 Apr 2024 00:57:53 +0530 Subject: [PATCH 04/24] Modified id with camel case convention and Revised the name to be more concise --- .github/workflows/wiki.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index 66ab33d7ca3..b3028fc7807 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -11,7 +11,8 @@ on: jobs: table_of_contents_check: - name: Wiki Check Table of Contents match Headers + # To verify that the wiki's table of contents matches the headers accurately. + name: Check Wiki Table of Contents runs-on: ubuntu-20.04 env: CACHE_DIRECTORY: ~/.bazel_cache @@ -23,8 +24,8 @@ jobs: with: version: 4.0.0 - - name: Wiki Check Table of Contents - id: wikichecktoc + - name: Check Wiki Table of Contents + id: checkWikiToc run: | bazel run //scripts:wiki_table_of_contents_check -- ${GITHUB_WORKSPACE} From 49917c7b73014e276c43389256ab1975f5e4925a Mon Sep 17 00:00:00 2001 From: Rd Date: Fri, 5 Jul 2024 08:05:25 +0530 Subject: [PATCH 05/24] Renaming wiki dir variables for better clarity --- .../scripts/wiki/WikiTableOfContentsCheck.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index 9a22731c376..920cfd58ad9 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -16,12 +16,12 @@ import java.io.File */ fun main(vararg args: String) { // Path to the repo's wiki. - val githubWorkspace = "${args[0]}/wiki/" - val wikiDirectory = File(githubWorkspace) + val wikiDirPath = "${args[0]}/wiki/" + val wikiDir = File(wikiDirPath) // Check if the wiki directory exists. - if (wikiDirectory.exists() && wikiDirectory.isDirectory) { - processWikiDirectory(wikiDirectory) + if (wikiDir.exists() && wikiDir.isDirectory) { + processWikiDirectory(wikiDir) } else { println("No contents found in the Wiki directory.") } @@ -30,10 +30,10 @@ fun main(vararg args: String) { /** * Checks every file in the wiki repo. * - * @param wikiDirectory the default working directory + * @param wikiDir the default working directory */ -fun processWikiDirectory(wikiDirectory: File) { - wikiDirectory.listFiles()?.forEach { file -> +fun processWikiDirectory(wikiDir: File) { + wikiDir.listFiles()?.forEach { file -> processWikiFile(file) } } From 94fa4f6e0bb5186941741d55da45e515d74c8090 Mon Sep 17 00:00:00 2001 From: Rd Date: Fri, 5 Jul 2024 11:48:11 +0530 Subject: [PATCH 06/24] Simplified the wiki table of content check logic with kotlin functions --- .../scripts/wiki/WikiTableOfContentsCheck.kt | 50 ++++++++++++++--- .../oppia/android/scripts/wiki/BUILD.bazel | 16 ++++++ .../wiki/WikiTableOfContentsCheckTest.kt | 55 +++++++++++++++++++ 3 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 scripts/src/javatests/org/oppia/android/scripts/wiki/BUILD.bazel create mode 100644 scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index 920cfd58ad9..4d17544524e 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -22,6 +22,7 @@ fun main(vararg args: String) { // 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.") } @@ -34,20 +35,53 @@ fun main(vararg args: String) { */ fun processWikiDirectory(wikiDir: File) { wikiDir.listFiles()?.forEach { file -> - processWikiFile(file) + checkTableOfContents(file) } } /** - * Processes the contents of a single wiki file to ensure the accuracy of the Table of Contents. + * Checks the contents of a single wiki file to ensure the accuracy of the Table of Contents. * * @param file the wiki file to process. */ -fun processWikiFile(file: File) { - var inTableOfContents = false - var skipBlankLine = false +fun checkTableOfContents(file: File) { +// var inTableOfContents = false +// var skipBlankLine = false - file.forEachLine { line -> + println("File: $file") + val fileContents = file.readLines() + val tocStartIdx = fileContents.indexOfFirst { + it.contains("## Table of Contents") + } + + println("start: $tocStartIdx") + if (tocStartIdx == -1) { + println("No Table of Contents found for the file $file") + return + } + + /*val blankLineIdx = fileContents.subList(tocStartIdx, fileContents.size).indexOfFirst { + it.isBlank() + } + println("blank: $blankLineIdx")*/ + + // Skipping the blank line after the ## Table of Contents + val eOfIdx = fileContents.subList(tocStartIdx + 2, fileContents.size).indexOfFirst { + it.isBlank() + } + println("end: $eOfIdx") + if (eOfIdx == -1) throw Exception("Table of Contents didn't end with a blank line") + + val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + eOfIdx + 1) + println("Toc line: $tocSpecificLines") + + for (line in tocSpecificLines) { + if (line.trimStart().startsWith("- [") && !line.contains("https://")) { + validateTableOfContents(file, line) + } + } + +/* file.forEachLine { line -> when { // Checking for Table of Contents section. line.trim() == "## Table of Contents" -> { @@ -63,7 +97,7 @@ fun processWikiFile(file: File) { // Checking for end of Table of Contents section. inTableOfContents && line.isBlank() -> inTableOfContents = false } - } + }*/ } /** @@ -86,7 +120,7 @@ fun validateTableOfContents(file: File, line: String) { // Checks if the table of content title matches with the header link text. val matches = title.equals(link, ignoreCase = true) if (!matches) { - throw Exception( + throw Exception("\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)}'." diff --git a/scripts/src/javatests/org/oppia/android/scripts/wiki/BUILD.bazel b/scripts/src/javatests/org/oppia/android/scripts/wiki/BUILD.bazel new file mode 100644 index 00000000000..953b3f7d8d9 --- /dev/null +++ b/scripts/src/javatests/org/oppia/android/scripts/wiki/BUILD.bazel @@ -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", + ], +) diff --git a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt new file mode 100644 index 00000000000..9a7a2eedc95 --- /dev/null +++ b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt @@ -0,0 +1,55 @@ +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 + + @field:[Rule JvmField] val tempFolder = TemporaryFolder() + + @Before + fun setUp() { + System.setOut(PrintStream(outContent)) + } + + @After + fun tearDown() { + System.setOut(originalOut) + } + + @Test + fun testValidToCWithMatchingHeaders() { + tempFolder.newFolder("wiki") + val file = tempFolder.newFile("wiki/ValidToCWithMatchingHeaders.md") + file.writeText(""" + ## Table of Contents + + - [Introduction](#introduction) + - [Usage](#usage) + + ## Introduction + Content + + ## Usage + Content + """.trimIndent()) + + runScript() + + assertThat(outContent.toString().trim()).contains("WIKI TABLE OF CONTENTS CHECK PASSED") + } + + private fun runScript() { + main(tempFolder.root.absolutePath) + } +} \ No newline at end of file From 3e74a99b48a3c038773d0e4fb7c9863453a4e4d3 Mon Sep 17 00:00:00 2001 From: Rd Date: Fri, 5 Jul 2024 11:52:52 +0530 Subject: [PATCH 07/24] Code clean up and replaced exception with error statement --- .../scripts/wiki/WikiTableOfContentsCheck.kt | 34 ++----------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index 4d17544524e..d6188e09755 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -45,32 +45,20 @@ fun processWikiDirectory(wikiDir: File) { * @param file the wiki file to process. */ fun checkTableOfContents(file: File) { -// var inTableOfContents = false -// var skipBlankLine = false - - println("File: $file") val fileContents = file.readLines() val tocStartIdx = fileContents.indexOfFirst { it.contains("## Table of Contents") } - - println("start: $tocStartIdx") if (tocStartIdx == -1) { println("No Table of Contents found for the file $file") return } - /*val blankLineIdx = fileContents.subList(tocStartIdx, fileContents.size).indexOfFirst { - it.isBlank() - } - println("blank: $blankLineIdx")*/ - // Skipping the blank line after the ## Table of Contents val eOfIdx = fileContents.subList(tocStartIdx + 2, fileContents.size).indexOfFirst { it.isBlank() } - println("end: $eOfIdx") - if (eOfIdx == -1) throw Exception("Table of Contents didn't end with a blank line") + if (eOfIdx == -1) error("Table of Contents didn't end with a blank line") val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + eOfIdx + 1) println("Toc line: $tocSpecificLines") @@ -80,24 +68,6 @@ fun checkTableOfContents(file: File) { validateTableOfContents(file, line) } } - -/* file.forEachLine { line -> - when { - // Checking for Table of Contents section. - line.trim() == "## Table of Contents" -> { - inTableOfContents = true - skipBlankLine = true - } - // Checking to skip the blank line immediately after the ## Table of Contents. - skipBlankLine && line.isBlank() -> skipBlankLine = false - // Validating the contents in the Table of Content. - inTableOfContents && line.trimStart().startsWith("- [") && !line.contains("https://") -> { - validateTableOfContents(file, line) - } - // Checking for end of Table of Contents section. - inTableOfContents && line.isBlank() -> inTableOfContents = false - } - }*/ } /** @@ -120,7 +90,7 @@ fun validateTableOfContents(file: File, line: String) { // Checks if the table of content title matches with the header link text. val matches = title.equals(link, ignoreCase = true) if (!matches) { - throw Exception("\nWIKI TABLE OF CONTENTS CHECK FAILED" + + 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)}'." From 5a8b4b9a5839afa0a81e482833e90853e7138641 Mon Sep 17 00:00:00 2001 From: Rd Date: Fri, 5 Jul 2024 12:26:57 +0530 Subject: [PATCH 08/24] Added test cases for wiki toc checks --- .../wiki/WikiTableOfContentsCheckTest.kt | 94 ++++++++++++++++++- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt index 9a7a2eedc95..735aa8679cf 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt @@ -14,11 +14,14 @@ import java.io.PrintStream 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() { + tempFolder.newFolder("wiki") System.setOut(PrintStream(outContent)) } @@ -28,9 +31,8 @@ class WikiTableOfContentsCheckTest { } @Test - fun testValidToCWithMatchingHeaders() { - tempFolder.newFolder("wiki") - val file = tempFolder.newFile("wiki/ValidToCWithMatchingHeaders.md") + fun testWikiTOCCheck_validWikiTOC_checkPass() { + val file = tempFolder.newFile("wiki/wiki.md") file.writeText(""" ## Table of Contents @@ -46,7 +48,91 @@ class WikiTableOfContentsCheckTest { runScript() - assertThat(outContent.toString().trim()).contains("WIKI TABLE OF CONTENTS CHECK PASSED") + assertThat(outContent.toString().trim()).contains(WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR) + } + + @Test + fun testWikiTOCCheck_missingWikiTOC_returnsNoTOCFound() { + val file = tempFolder.newFile("wiki/wiki.md") + file.writeText(""" + - [Introduction](#introduction) + - [Usage](#usage) + + ## Introduction + Content + + ## Usage + Content + """.trimIndent()) + + runScript() + + assertThat(outContent.toString().trim()).contains("No Table of Contents found") + } + + @Test + fun testWikiTOCCheck_mismatchWikiTOC_checkFail() { + val file = tempFolder.newFile("wiki/wiki.md") + file.writeText(""" + ## Table of Contents + + - [Introduction](#introductions) + - [Usage](#usage) + + ## Introduction + Content + + ## Usage + Content + """.trimIndent()) + + val exception = assertThrows() { + runScript() + } + + assertThat(exception).hasMessageThat().contains(WIKI_TOC_CHECK_FAILED_OUTPUT_INDICATOR) + } + + @Test + fun testWikiTOCCheck_validWikiTOCWithSeparator_checkPass() { + 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() { + 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() { From 9e4386ae1837d31720a1ae3ea288d08188dbed38 Mon Sep 17 00:00:00 2001 From: Rd Date: Fri, 5 Jul 2024 13:00:12 +0530 Subject: [PATCH 09/24] Fix Lint Checks for indentation and missing spaces --- .../scripts/wiki/WikiTableOfContentsCheck.kt | 5 +-- .../wiki/WikiTableOfContentsCheckTest.kt | 32 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index d6188e09755..18cb650f1f8 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -90,8 +90,9 @@ fun validateTableOfContents(file: File, line: String) { // 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}. " + + 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)}'." ) diff --git a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt index 735aa8679cf..fab1892b7eb 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt @@ -33,7 +33,8 @@ class WikiTableOfContentsCheckTest { @Test fun testWikiTOCCheck_validWikiTOC_checkPass() { val file = tempFolder.newFile("wiki/wiki.md") - file.writeText(""" + file.writeText( + """ ## Table of Contents - [Introduction](#introduction) @@ -44,7 +45,8 @@ class WikiTableOfContentsCheckTest { ## Usage Content - """.trimIndent()) + """.trimIndent() + ) runScript() @@ -54,7 +56,8 @@ class WikiTableOfContentsCheckTest { @Test fun testWikiTOCCheck_missingWikiTOC_returnsNoTOCFound() { val file = tempFolder.newFile("wiki/wiki.md") - file.writeText(""" + file.writeText( + """ - [Introduction](#introduction) - [Usage](#usage) @@ -63,7 +66,8 @@ class WikiTableOfContentsCheckTest { ## Usage Content - """.trimIndent()) + """.trimIndent() + ) runScript() @@ -73,7 +77,8 @@ class WikiTableOfContentsCheckTest { @Test fun testWikiTOCCheck_mismatchWikiTOC_checkFail() { val file = tempFolder.newFile("wiki/wiki.md") - file.writeText(""" + file.writeText( + """ ## Table of Contents - [Introduction](#introductions) @@ -84,7 +89,8 @@ class WikiTableOfContentsCheckTest { ## Usage Content - """.trimIndent()) + """.trimIndent() + ) val exception = assertThrows() { runScript() @@ -96,7 +102,8 @@ class WikiTableOfContentsCheckTest { @Test fun testWikiTOCCheck_validWikiTOCWithSeparator_checkPass() { val file = tempFolder.newFile("wiki/wiki.md") - file.writeText(""" + file.writeText( + """ ## Table of Contents - [Introduction To Wiki](#introduction-to-wiki) @@ -107,7 +114,8 @@ class WikiTableOfContentsCheckTest { ## Usage Content - """.trimIndent()) + """.trimIndent() + ) runScript() @@ -117,7 +125,8 @@ class WikiTableOfContentsCheckTest { @Test fun testWikiTOCCheck_validWikiTOCWithSpecialCharacter_checkPass() { val file = tempFolder.newFile("wiki/wiki.md") - file.writeText(""" + file.writeText( + """ ## Table of Contents - [Introduction](#introduction?) @@ -128,7 +137,8 @@ class WikiTableOfContentsCheckTest { ## Usage Content - """.trimIndent()) + """.trimIndent() + ) runScript() @@ -138,4 +148,4 @@ class WikiTableOfContentsCheckTest { private fun runScript() { main(tempFolder.root.absolutePath) } -} \ No newline at end of file +} From 9193d15254670a842e4d7da1747f372f8bc3e9cf Mon Sep 17 00:00:00 2001 From: Rd Date: Fri, 5 Jul 2024 13:08:53 +0530 Subject: [PATCH 10/24] Fix Lint check buildifier reformat --- scripts/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/BUILD.bazel b/scripts/BUILD.bazel index 9b95059e3f1..1d564d127ba 100644 --- a/scripts/BUILD.bazel +++ b/scripts/BUILD.bazel @@ -242,7 +242,7 @@ kt_jvm_binary( testonly = True, main_class = "org.oppia.android.scripts.wiki.WikiTableOfContentsCheckKt", runtime_deps = [ - "//scripts/src/java/org/oppia/android/scripts/wiki:wiki_table_of_contents_check_lib" + "//scripts/src/java/org/oppia/android/scripts/wiki:wiki_table_of_contents_check_lib", ], ) From 72d0a2b5b9f88dc09a0d8b4e513ae963bf43413a Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 5 Sep 2024 15:06:41 +0530 Subject: [PATCH 11/24] Added missing test cases for no directory found to hit 100% coverage --- .../wiki/WikiTableOfContentsCheckTest.kt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt index fab1892b7eb..97a34b91f36 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt @@ -21,7 +21,6 @@ class WikiTableOfContentsCheckTest { @Before fun setUp() { - tempFolder.newFolder("wiki") System.setOut(PrintStream(outContent)) } @@ -30,8 +29,22 @@ class WikiTableOfContentsCheckTest { 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( """ @@ -55,6 +68,7 @@ class WikiTableOfContentsCheckTest { @Test fun testWikiTOCCheck_missingWikiTOC_returnsNoTOCFound() { + tempFolder.newFolder("wiki") val file = tempFolder.newFile("wiki/wiki.md") file.writeText( """ @@ -76,6 +90,7 @@ class WikiTableOfContentsCheckTest { @Test fun testWikiTOCCheck_mismatchWikiTOC_checkFail() { + tempFolder.newFolder("wiki") val file = tempFolder.newFile("wiki/wiki.md") file.writeText( """ @@ -101,6 +116,7 @@ class WikiTableOfContentsCheckTest { @Test fun testWikiTOCCheck_validWikiTOCWithSeparator_checkPass() { + tempFolder.newFolder("wiki") val file = tempFolder.newFile("wiki/wiki.md") file.writeText( """ @@ -124,6 +140,7 @@ class WikiTableOfContentsCheckTest { @Test fun testWikiTOCCheck_validWikiTOCWithSpecialCharacter_checkPass() { + tempFolder.newFolder("wiki") val file = tempFolder.newFile("wiki/wiki.md") file.writeText( """ From b5c9cf3b8d1f2e87c468c6e9a09ebde6d021f701 Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 2 Oct 2024 17:32:20 +0530 Subject: [PATCH 12/24] Upgraded the Bazel version, removed cache env, used Regex to check heading text --- .github/workflows/wiki.yml | 4 +--- .../oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index 5f7f34a13d1..4568a6469db 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -14,15 +14,13 @@ jobs: # To verify that the wiki's table of contents matches the headers accurately. name: Check Wiki Table of Contents runs-on: ubuntu-20.04 - env: - CACHE_DIRECTORY: ~/.bazel_cache steps: - uses: actions/checkout@v2 - name: Set up Bazel uses: abhinavsingh/setup-bazel@v3 with: - version: 4.0.0 + version: 6.5.0 - name: Check Wiki Table of Contents id: checkWikiToc diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index 18cb650f1f8..489ff4e41cc 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -47,7 +47,7 @@ fun processWikiDirectory(wikiDir: File) { fun checkTableOfContents(file: File) { val fileContents = file.readLines() val tocStartIdx = fileContents.indexOfFirst { - it.contains("## Table of Contents") + it.contains(Regex("""##\s+Table\s+of\s+Contents""", RegexOption.IGNORE_CASE)) } if (tocStartIdx == -1) { println("No Table of Contents found for the file $file") @@ -58,7 +58,7 @@ fun checkTableOfContents(file: File) { val eOfIdx = fileContents.subList(tocStartIdx + 2, fileContents.size).indexOfFirst { it.isBlank() } - if (eOfIdx == -1) error("Table of Contents didn't end with a blank line") + if (eOfIdx == -1) error("Table of Contents didn't end with a blank line.") val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + eOfIdx + 1) println("Toc line: $tocSpecificLines") From afaf59e92db26b26262560c20e30cdac0131e1da Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 3 Oct 2024 18:14:16 +0530 Subject: [PATCH 13/24] Added pull-request trigger to check on every PR creation, removed debug lines and removed the confetti emoji filtering --- .github/workflows/wiki.yml | 1 + .../oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index 4568a6469db..1badfd225b3 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -1,5 +1,6 @@ name: Deploy to Wiki on: + pull_request: push: branches: - develop diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index 489ff4e41cc..c634792e7a9 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -50,7 +50,6 @@ fun checkTableOfContents(file: File) { it.contains(Regex("""##\s+Table\s+of\s+Contents""", RegexOption.IGNORE_CASE)) } if (tocStartIdx == -1) { - println("No Table of Contents found for the file $file") return } @@ -61,7 +60,6 @@ fun checkTableOfContents(file: File) { if (eOfIdx == -1) error("Table of Contents didn't end with a blank line.") val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + eOfIdx + 1) - println("Toc line: $tocSpecificLines") for (line in tocSpecificLines) { if (line.trimStart().startsWith("- [") && !line.contains("https://")) { @@ -85,7 +83,7 @@ fun validateTableOfContents(file: File, line: String) { val linkRegex = "\\(#(.*?)\\)".toRegex() val link = linkRegex.find(line)?.groupValues?.get(1)?.removePrefix("#")?.replace('-', ' ') ?.replace(Regex("[?&./:’'*!,(){}\\[\\]+]"), "") - ?.replace("confetti_ball", "")?.trim() + ?.trim() // Checks if the table of content title matches with the header link text. val matches = title.equals(link, ignoreCase = true) From be0015172720e07ae04acafef4d58ab5cfbb9c6b Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 3 Oct 2024 18:32:04 +0530 Subject: [PATCH 14/24] Trigger only when changes are made to the wiki dir --- .github/workflows/wiki.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index 1badfd225b3..40a80ffa5b8 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -1,6 +1,8 @@ name: Deploy to Wiki on: pull_request: + paths: + - 'wiki/**' push: branches: - develop From c18ac91813523cb3b7db5146176e39b6f490c1e1 Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 3 Oct 2024 18:39:54 +0530 Subject: [PATCH 15/24] Conditional execution of the wiki-deploy to only proceed if the event is push to the develop branch --- .github/workflows/wiki.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index 40a80ffa5b8..1875e6154be 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -35,6 +35,7 @@ jobs: strategy: matrix: os: [ubuntu-20.04] + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }} steps: - uses: actions/checkout@v3 with: From 2dfd045fa9193ea6bc45310fcfc29885e6fb19d1 Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 3 Oct 2024 19:00:30 +0530 Subject: [PATCH 16/24] Removed the test case for checking TOC present as the log statement to display the TOC not found is removed now The log statement is removed as it is unnecessary and clutters the check stack trace and also it isn't mandatory to have a TOC on every page so the check is not needed. --- .../wiki/WikiTableOfContentsCheckTest.kt | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt index 97a34b91f36..f5c66abf2cd 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt @@ -66,28 +66,6 @@ class WikiTableOfContentsCheckTest { 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("No Table of Contents found") - } - @Test fun testWikiTOCCheck_mismatchWikiTOC_checkFail() { tempFolder.newFolder("wiki") From c7d0d1136d8eeeb43516eee90930c18bb316c68b Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 3 Oct 2024 19:38:16 +0530 Subject: [PATCH 17/24] Re-adding the test case to hit coverage but now checking with final result as the toc not found statement is removed --- .../wiki/WikiTableOfContentsCheckTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt index f5c66abf2cd..8b91a453107 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt @@ -66,6 +66,28 @@ class WikiTableOfContentsCheckTest { 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_mismatchWikiTOC_checkFail() { tempFolder.newFolder("wiki") From 7cbad112c8de98b4fcfa01d00c0406c189085a50 Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 9 Oct 2024 19:55:17 +0530 Subject: [PATCH 18/24] Updating the mis-matched TOC to confirm the TOC check status --- wiki/Installing-Oppia-Android.md | 2 +- wiki/Interpreting-CI-Results.md | 2 +- wiki/Oppia-Android-Code-Coverage.md | 8 ++++---- ...ing-tests-with-good-behavioral-coverage.md | 20 +++++++++---------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/wiki/Installing-Oppia-Android.md b/wiki/Installing-Oppia-Android.md index ffc19cba8bd..dcf0a4baafb 100644 --- a/wiki/Installing-Oppia-Android.md +++ b/wiki/Installing-Oppia-Android.md @@ -7,7 +7,7 @@ This wiki page explains how to install Oppia Android on your local machine. If y - [Prepare developer environment](#prepare-developer-environment) - [Install oppia-android](#install-oppia-android) - [Run the app from Android Studio](#run-the-app-from-android-studio) -- [Run the tests](#set-up-and-run-tests) +- [Set up and Run tests](#set-up-and-run-tests) - [Step-by-Step guidance for setting up and running app modules robolectric test](#step-by-step-guidance-for-setting-up-and-running-app-modules-robolectric-test) - [For tests that are in non-app modules, such as **domain** or **utility**:](#for-tests-that-are-in-non-app-modules-such-as-domain-or-utility) diff --git a/wiki/Interpreting-CI-Results.md b/wiki/Interpreting-CI-Results.md index 2adf2685b53..00b3c5667c7 100644 --- a/wiki/Interpreting-CI-Results.md +++ b/wiki/Interpreting-CI-Results.md @@ -1,6 +1,6 @@ ## Table of Contents -- [How to find the error message for a Failing CI check](#how-to-find-error-message-for-failing-ci-checks) +- [How to find error message for Failing CI checks](#how-to-find-error-message-for-failing-ci-checks) - [Developer Video - Understanding CI check failures](#developer-video---understanding-ci-check-failures) ## How to find error message for Failing CI checks diff --git a/wiki/Oppia-Android-Code-Coverage.md b/wiki/Oppia-Android-Code-Coverage.md index 499b3591642..0d294887e8f 100644 --- a/wiki/Oppia-Android-Code-Coverage.md +++ b/wiki/Oppia-Android-Code-Coverage.md @@ -4,10 +4,10 @@ - [Understanding Code Coverage](#understanding-code-coverage) - [Why is Code Coverage Important?](#why-is-code-coverage-important) - [How to use the code coverage tool?](#how-to-use-the-code-coverage-tool) - - [Continuous Itegration Checks on Pull Request](#1-continuous-integration-checks-on-pull-requests) - - [Understanding the CI Coverage Report](#11-understanding-the-ci-coverage-report) - - [Local Command Line Interface Tools](#2-local-command-line-interface-cli-tools) - - [Understanding the Html Reports](#21-understanding-the-ci-coverage-report) + - [1. Continuous Integration Checks on Pull Requests](#1-continuous-integration-checks-on-pull-requests) + - [1.1 Understanding the CI Coverage Report](#11-understanding-the-ci-coverage-report) + - [2. Local Command Line Interface (CLI) Tools](#2-local-command-line-interface-cli-tools) + - [2.1 Understanding the CI Coverage Report](#21-understanding-the-ci-coverage-report) - [Increasing Code Coverage Metrics](#increasing-code-coverage-metrics) - [Unit-Centric Coverage Philosophy](#unit-centric-coverage-philosophy) - [Limitations of the code coverage tool](#limitations-of-the-code-coverage-tool) diff --git a/wiki/Writing-tests-with-good-behavioral-coverage.md b/wiki/Writing-tests-with-good-behavioral-coverage.md index db50cfa83a6..93b94ac7375 100644 --- a/wiki/Writing-tests-with-good-behavioral-coverage.md +++ b/wiki/Writing-tests-with-good-behavioral-coverage.md @@ -3,18 +3,18 @@ - [What is Behavioral Coverage?](#what-is-behavioral-coverage) - [Understanding Behavioral Coverage and its Importance](#understanding-behavioral-coverage-and-its-importance) - [Writing Effective Tests](#writing-effective-tests) - - [Understand the Requirements](#1-understanding-the-requirements) - - [Writing Clear and Descriptive Test Cases](#2-writing-clear-and-descriptive-test-cases) - - [Focusing on Specific Test Cases](#3-focusing-on-specific-test-cases) - - [Covering Different Scenarios](#4-covering-different-scenarios) - - [Covering All Branches, Paths, and Conditions](#5-covering-all-branches-paths-and-conditions) - - [Exception and Error Handling](#6-exception-and-error-handling) - - [Absence of Unwanted Output](#7-absence-of-unwanted-output) + - [1. Understanding the Requirements](#1-understanding-the-requirements) + - [2. Writing Clear and Descriptive Test Cases](#2-writing-clear-and-descriptive-test-cases) + - [3. Focusing on Specific Test Cases](#3-focusing-on-specific-test-cases) + - [4. Covering Different Scenarios](#4-covering-different-scenarios) + - [5. Covering All Branches, Paths, and Conditions](#5-covering-all-branches-paths-and-conditions) + - [6. Exception and Error Handling](#6-exception-and-error-handling) + - [7. Absence of Unwanted Output](#7-absence-of-unwanted-output) - [Testing Public APIs](#testing-public-apis) - [Structuring Test Bodies](#structuring-test-bodies) - - [When and How to Divide Responsibilities](#1-when-and-how-to-divide-responsibilities) - - [When Not to Divide Responsibilities](#2-when-not-to-divide-responsibilities) - - [Importance of Descriptive Test Names](#3-importance-of-descriptive-test-names) + - [1. When and How to Divide Responsibilities](#1-when-and-how-to-divide-responsibilities) + - [2. When Not to Divide Responsibilities](#2-when-not-to-divide-responsibilities) + - [3. Importance of Descriptive Test Names](#3-importance-of-descriptive-test-names) - [How to Map a Line of Code to Its Corresponding Behaviors?](#how-to-map-a-line-of-code-to-its-corresponding-behaviors) # What is Behavioral Coverage? From e9af4abb053553de033417dd591e016c5a8caa7a Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 9 Oct 2024 20:02:28 +0530 Subject: [PATCH 19/24] Adding concurrency to wiki actions as it continues to run on subsequent triggers --- .github/workflows/wiki.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index 1875e6154be..57f63fe6fb7 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -12,6 +12,10 @@ on: # (see https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#gollum). gollum: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: true + jobs: table_of_contents_check: # To verify that the wiki's table of contents matches the headers accurately. From 711071593d0905e23467ad009042287cfe707615 Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 9 Oct 2024 21:39:57 +0530 Subject: [PATCH 20/24] Modified the visibilities and removed private fun Kdocs, also updated the end index to span Limit index which previously excluded the last toc element as eOfIdx was calculated as the subList from the start index + 2 --- .../scripts/wiki/WikiTableOfContentsCheck.kt | 31 +++++-------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index c634792e7a9..4eb47b54bdd 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -28,23 +28,13 @@ fun main(vararg args: String) { } } -/** - * Checks every file in the wiki repo. - * - * @param wikiDir the default working directory - */ -fun processWikiDirectory(wikiDir: File) { +private fun processWikiDirectory(wikiDir: File) { wikiDir.listFiles()?.forEach { file -> checkTableOfContents(file) } } -/** - * Checks the contents of a single wiki file to ensure the accuracy of the Table of Contents. - * - * @param file the wiki file to process. - */ -fun checkTableOfContents(file: 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)) @@ -54,12 +44,13 @@ fun checkTableOfContents(file: File) { } // Skipping the blank line after the ## Table of Contents - val eOfIdx = fileContents.subList(tocStartIdx + 2, fileContents.size).indexOfFirst { + val spanLimitIdx = fileContents.subList(tocStartIdx + 2, fileContents.size).indexOfFirst { it.isBlank() - } - if (eOfIdx == -1) error("Table of Contents didn't end with a blank line.") + }.takeIf { it != -1 } + ?.plus(1) + ?: error ("Table of Contents didn't end with a blank line.") - val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + eOfIdx + 1) + val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + spanLimitIdx + 1) for (line in tocSpecificLines) { if (line.trimStart().startsWith("- [") && !line.contains("https://")) { @@ -68,13 +59,7 @@ fun checkTableOfContents(file: File) { } } -/** - * Validates the accuracy of a Table of Contents entry in a wiki file. - * - * @param file the wiki file being validated. - * @param line the line containing the Table of Contents entry. - */ -fun validateTableOfContents(file: File, line: String) { +private fun validateTableOfContents(file: File, line: String) { val titleRegex = "\\[(.*?)\\]".toRegex() val title = titleRegex.find(line)?.groupValues?.get(1)?.replace('-', ' ') ?.replace(Regex("[?&./:’'*!,(){}\\[\\]+]"), "") From 0077bd4421991c2bf272d1fd817c93c79fe3176c Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 9 Oct 2024 21:48:23 +0530 Subject: [PATCH 21/24] Fix ktlint unexpected spacing before ( --- .../org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index 4eb47b54bdd..6c39a236fbc 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -48,7 +48,7 @@ private fun checkTableOfContents(file: File) { it.isBlank() }.takeIf { it != -1 } ?.plus(1) - ?: error ("Table of Contents didn't end with a blank line.") + ?: error("Table of Contents didn't end with a blank line.") val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + spanLimitIdx + 1) From 1d842fc41049a624c5191ec243c047d7a620e01e Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 9 Oct 2024 22:04:40 +0530 Subject: [PATCH 22/24] Adding confetti emoji to match with the header link --- wiki/Guidance-on-submitting-a-PR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki/Guidance-on-submitting-a-PR.md b/wiki/Guidance-on-submitting-a-PR.md index 0124b44eb90..37b731e6f64 100644 --- a/wiki/Guidance-on-submitting-a-PR.md +++ b/wiki/Guidance-on-submitting-a-PR.md @@ -22,7 +22,7 @@ Note: If your change involves more than around 500 lines of code, we recommend f - [Tips for getting your PR submitted](#tips-for-getting-your-pr-submitted) - [Appendix: Resolving merge conflicts using the terminal](#appendix-resolving-merge-conflicts-using-the-terminal) - [Appendix: Resolving merge conflicts using Android Studio](#appendix-resolving-merge-conflicts-using-android-studio) -- [Step 4: Tidy up and celebrate!](#step-4-tidy-up-and-celebrate-confetti_ball) +- [Step 4: Tidy up and celebrate! :confetti_ball:](#step-4-tidy-up-and-celebrate-confetti_ball) ## Step 1: Making a local code change From fa76163ea998f9591ee1ee6c6c6b66e97ee5dd17 Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 9 Oct 2024 23:58:07 +0530 Subject: [PATCH 23/24] Replaced checking toc end by blank endline with header tags as they are more accurate than possible duplicate blank lines and also headers presence check would confirm the headers present in the TOC are also available in the wiki page --- .../scripts/wiki/WikiTableOfContentsCheck.kt | 9 ++++----- .../wiki/WikiTableOfContentsCheckTest.kt | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt index 6c39a236fbc..2f5a0ae3862 100644 --- a/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt +++ b/scripts/src/java/org/oppia/android/scripts/wiki/WikiTableOfContentsCheck.kt @@ -44,13 +44,12 @@ private fun checkTableOfContents(file: File) { } // Skipping the blank line after the ## Table of Contents - val spanLimitIdx = fileContents.subList(tocStartIdx + 2, fileContents.size).indexOfFirst { - it.isBlank() + val tocEndIdx = fileContents.subList(tocStartIdx + 2, fileContents.size).indexOfFirst { + it.startsWith("#") }.takeIf { it != -1 } - ?.plus(1) - ?: error("Table of Contents didn't end with a blank line.") + ?: error("Wiki doesn't contain headers referenced in Table of Contents.") - val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + spanLimitIdx + 1) + val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + tocEndIdx + 1) for (line in tocSpecificLines) { if (line.trimStart().startsWith("- [") && !line.contains("https://")) { diff --git a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt index 8b91a453107..9b824f14207 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt @@ -88,6 +88,26 @@ class WikiTableOfContentsCheckTest { 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() { + runScript() + } + + assertThat(exception).hasMessageThat().contains("Wiki doesn't contain headers referenced in Table of Contents.") + } + @Test fun testWikiTOCCheck_mismatchWikiTOC_checkFail() { tempFolder.newFolder("wiki") From 609df11b67ade2a93dd520bdb1f6e81ac16778e4 Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 9 Oct 2024 23:59:54 +0530 Subject: [PATCH 24/24] Fixed ktlint max line exceeded --- .../android/scripts/wiki/WikiTableOfContentsCheckTest.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt index 9b824f14207..d90593dfa2e 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/wiki/WikiTableOfContentsCheckTest.kt @@ -105,7 +105,9 @@ class WikiTableOfContentsCheckTest { runScript() } - assertThat(exception).hasMessageThat().contains("Wiki doesn't contain headers referenced in Table of Contents.") + assertThat(exception).hasMessageThat().contains( + "Wiki doesn't contain headers referenced in Table of Contents." + ) } @Test