# Run unit and widget tests.
#
# Run this script in the `src` (root folder).
#
# This will create a `coverage` folder in that directory containing the
# code coverage results of the test runs. 
#
# Your project structure should be like this:
#
# -src/ (ROOT FOLDER)
#    -project_1/
#        -test/
#        -pubspec.yaml
#    -project_2/
#        -test/
#        -pubspec.yaml
#    -project_3/
#        -test/
#        -pubspec.yaml
#    -project_blahblah/
#        -test/
#        -pubspec.yaml

# Change current working directory to `src`
cd "src"

# Install lcov using Homebrew. Works only in Linux and MacOS.
# https://formulae.brew.sh/formula/lcov
brew install lcov

# Install lcov files merger using Node Package Manager.
# https://www.npmjs.com/package/lcov-result-merger
npm install -g lcov-result-merger

# Install lcov files merger using Node Package Manager.
# https://www.npmjs.com/package/junit-merge
npm install -g junit-merge

# Install lcov files merger using Pub Package Manager.
# https://pub.dev/packages/junitreport
pub global activate junitreport

# Set variables to be used.
ROOT_DIR=$PWD
TESTS_RAN=0
TEST_RESULT_FOLDER_NAME="test_result"
TEST_RESULT_OUTPUT_DIR=$ROOT_DIR/$TEST_RESULT_FOLDER_NAME
CODE_COVERAGE_FOLDER_NAME="coverage"
CODE_COVERAGE_OUTPUT_DIR=$ROOT_DIR/$CODE_COVERAGE_FOLDER_NAME

# Delete previous coverage results, if any.
if [ -d "$CODE_COVERAGE_OUTPUT_DIR" ]; then
    echo 'Deleting previous coverage results...'
    rm -r "$CODE_COVERAGE_OUTPUT_DIR"
fi

# Delete previous test results, if any.
if [ -d "$TEST_RESULT_OUTPUT_DIR" ]; then
    echo 'Deleting previous test results...'
    rm -r "$TEST_RESULT_OUTPUT_DIR"
fi

# Create code coverage output folder, if it does not exist.
if [ ! -d "$CODE_COVERAGE_OUTPUT_DIR" ]; then
    echo 'Creating code coverage output folder...'
    mkdir "$CODE_COVERAGE_OUTPUT_DIR"
fi

# Create test results output folder, if it does not exist.
if [ ! -d "$TEST_RESULT_OUTPUT_DIR" ]; then
    echo 'Creating test results output folder...'
    mkdir "$TEST_RESULT_OUTPUT_DIR"
fi

# Loop through all subdirectories.
for d in **/
do
    # Set variables relative to the project directory in which tests will be ran.
    CURRENT_PROJECT=${d%/}
    CODE_COVERAGE_NAME=$CURRENT_PROJECT.info
    CODE_COVERAGE_OUTPUT_PATH=$CODE_COVERAGE_OUTPUT_DIR/$CODE_COVERAGE_NAME
    TEST_RESULT_NAME=$CURRENT_PROJECT.xml
    TEST_RESULT_OUTPUT_PATH=$TEST_RESULT_OUTPUT_DIR/$TEST_RESULT_NAME

    # Change directory to the next project.
    cd "$d"

    # Check if `test` directory exists or `pubspec.yaml` file exists.
    # If any was not found, skip the directory. Else, run tests.
    if [ ! -d "test" ]; then
        echo "'test' folder was not found in $CURRENT_PROJECT, skipping..."
    elif [ ! -f "pubspec.yaml" ]; then
        echo "'pubspec.yaml' was not found in $CURRENT_PROJECT, skipping..."
    else
        echo "Running tests in $CURRENT_PROJECT"

        # Restore packages.
        flutter packages get

        # Run tests, collect test results, and publish to specified output path.
        flutter test --machine | tojunit -o "$TEST_RESULT_OUTPUT_PATH"
        
        # Run tests, collect code coverage, and publish result to specified output path.
        flutter test --coverage --coverage-path "$CODE_COVERAGE_OUTPUT_PATH"

        # Update the coverage info generated by appending the project folder name to the source file path.
        # If using MacOS, add double quotation marks ("") after -i. Else, remove it.
        sed -i "" "s-SF:-SF:$CURRENT_PROJECT/-g" "$CODE_COVERAGE_OUTPUT_PATH"

        (( TESTS_RAN++ ))
    fi

    # Return to the root directory.
    cd ..
done

# Check if test/s were ran.
# If so, merge and generate coverage report.
if (( TESTS_RAN > 0 )); then
    echo "$TESTS_RAN tests completed"

    # Merge code coverage results.
    echo "Merging code coverages..."
    lcov-result-merger "$CODE_COVERAGE_FOLDER_NAME/**" "$CODE_COVERAGE_FOLDER_NAME/merged-code-coverage.info"

    echo "Merging test results..."
    junit-merge -d "$TEST_RESULT_FOLDER_NAME" -o "$TEST_RESULT_FOLDER_NAME/merged-test-results.xml"

    # Generate HTML code coverage report.
    # $BUILD_BUILDNUMBER and $BUILD_SOURCEBRANCHNAME are defined in
    # Azure DevOps pipeline.
    echo "Generating HTML report..."
    genhtml -t "Build $BUILD_BUILDNUMBER on branch $BUILD_SOURCEBRANCHNAME" -o "$CODE_COVERAGE_FOLDER_NAME/html" "$CODE_COVERAGE_FOLDER_NAME/merged-code-coverage.info"
else
    echo "No test/s were ran."
fi