Skip to content

Commit

Permalink
Merge branch 'refs/heads/trunk' into 12074-woo-pos-move-floating-tool…
Browse files Browse the repository at this point in the history
…bar-to-the-home-screen-from-the-root
  • Loading branch information
kidinov committed Jul 24, 2024
2 parents 6d7d4bd + 139cbf7 commit 2aae80a
Show file tree
Hide file tree
Showing 130 changed files with 4,476 additions and 2,268 deletions.
25 changes: 11 additions & 14 deletions .buildkite/commands/run-unit-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,22 @@ fi


echo "--- 🚦 Report Tests Status"
path_pattern="*/build/test-results/*/*.xml"
results_files=()
while IFS= read -r -d '' file; do
results_files+=("$file")
done < <(find . -path "$path_pattern" -type f -name "*.xml" -print0)

for file in "${results_files[@]}"; do
if [[ $BUILDKITE_BRANCH == trunk ]] || [[ $BUILDKITE_BRANCH == release/* ]]; then
annotate_test_failures "$file" --slack "build-and-ship"
else
annotate_test_failures "$file"
fi
done
results_file="WooCommerce/build/test-results/merged-test-results.xml"
# Merge JUnit results into a single file (for performance reasons with reporting)
# See https://github.com/woocommerce/woocommerce-android/pull/12064
./merge_junit.sh -d WooCommerce/build/test-results/testJalapenoDebugUnitTest -o $results_file

if [[ $BUILDKITE_BRANCH == trunk ]] || [[ $BUILDKITE_BRANCH == release/* ]]; then
annotate_test_failures "$results_file" --slack "build-and-ship"
else
annotate_test_failures "$results_file"
fi

echo "--- ⚒️ Generating and uploading code coverage"
./gradlew jacocoTestReport
.buildkite/commands/upload-code-coverage.sh

echo "--- 🧪 Copying test logs for test collector"
mkdir WooCommerce/build/buildkite-test-analytics && cp WooCommerce/build/test-results/*/*.xml WooCommerce/build/buildkite-test-analytics
mkdir WooCommerce/build/buildkite-test-analytics && cp WooCommerce/build/test-results/*.xml WooCommerce/build/buildkite-test-analytics

exit $TESTS_EXIT_STATUS
7 changes: 0 additions & 7 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,6 @@ steps:
artifact_paths:
- "**/build/test-results/*/*.xml"

- label: "Ensure Screenshot Tests Build"
command: |
echo "--- ⚒️ Building"
cp gradle.properties-example gradle.properties
./gradlew assembleJalapenoDebugAndroidTest
plugins: [$CI_TOOLKIT]

- label: "Instrumented tests"
command: .buildkite/commands/run-instrumented-tests.sh
plugins:
Expand Down
3 changes: 0 additions & 3 deletions .buildkite/release-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
# This pipeline is meant to be run via the Buildkite API, and is
# only used for release builds

agents:
queue: "android"

agents:
queue: "android"

Expand Down
12 changes: 6 additions & 6 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
*** PLEASE FOLLOW THIS FORMAT: [<priority indicator, more stars = higher priority>] <description> [<PR URL>]
*** For entries which are touching the Android Wear app's, start entry with `[WEAR]` too.
19.6
19.7
-----
- [**] Payment Method is correctly assigned to orders marked as paid with cash [https://github.com/wordpress-mobile/WordPress-FluxC-Android/pull/3054]
19.6
-----
- [*] The more screen shows proper loading button statuses [https://github.com/woocommerce/woocommerce-android/pull/11968]
- [*] Improve stability of the OrderDetail screen [https://github.com/woocommerce/woocommerce-android/pull/12106]

19.6
-----
- [*] [Login] Improved login reliability by addressing some edge-case issues [https://github.com/woocommerce/woocommerce-android/pull/12033]
- [**] Stats: The Analytics Hub (accessed by tapping "View all store analytics" on the My Store dashboard) now includes analytics for Google Ads campaigns, when the Google Listings & Ads extension is active and connected to Google. [https://github.com/woocommerce/woocommerce-android/pull/12084]
- [**] Payment Method is correctly assigned to orders marked as paid with cash [https://github.com/wordpress-mobile/WordPress-FluxC-Android/pull/3054]
- [**] Product Creation AI V2: Milestone 1 which simplifies package photo flow and revamps UI. [https://github.com/woocommerce/woocommerce-android/issues/11800]
- [*] The more screen shows proper loading button statuses [https://github.com/woocommerce/woocommerce-android/pull/11968]
- [*] [Login] Improved login reliability by addressing some edge-case issues [https://github.com/woocommerce/woocommerce-android/pull/12033]

19.5
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ fun <T, R> Flow<T>.combineWithTimeout(
* A helper function to create a [MutableStateFlow] that creates an entry in [SavedStateHandle] to persist value
* through process-death.
*
* !BEWARE! that only data that can't be easily recovered should be stored - e.g. user's input. Storing complete
* viewStates wastes device resources and often leads to issues such as TransactionTooLarge crashes.
*
* Based on https://gist.github.com/marcellogalhardo/2a1ec56b7d00ba9af1ec9fd3583d53dc
*
* @param scope The scope used to synchronize the [StateFlow] and [SavedStateHandle]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class LoginViewModel @AssistedInject constructor(
@Assisted private val navController: NavHostController,
savedState: SavedStateHandle
) : WearViewModel() {
@Suppress("ForbiddenComment")
// TODO: Storing complete ViewState into SavedState can lead to TransactionTooLarge crashes. Only data that can't
// be easily recovered, such as user input, should be stored.
private val _viewState = savedState.getStateFlow(
scope = this,
initialValue = ViewState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class OrderDetailsViewModel @Inject constructor(
) : WearViewModel() {
private val orderId = savedState.get<Long>(ORDER_ID.key) ?: 0

@Suppress("ForbiddenComment")
// TODO: Storing complete ViewState into SavedState can lead to TransactionTooLarge crashes. Only data that can't
// be easily recovered, such as user input, should be stored.
private val _viewState = savedState.getStateFlow(
scope = this,
initialValue = ViewState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class OrdersListViewModel @AssistedInject constructor(
private val analyticsTracker: AnalyticsTracker,
savedState: SavedStateHandle
) : WearViewModel() {
@Suppress("ForbiddenComment")
// TODO: Storing complete ViewState into SavedState can lead to TransactionTooLarge crashes. Only data that can't
// be easily recovered, such as user input, should be stored.
private val _viewState = savedState.getStateFlow(
scope = this,
initialValue = ViewState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class StoreStatsViewModel @Inject constructor(
private val analyticsTracker: AnalyticsTracker,
savedState: SavedStateHandle
) : WearViewModel() {
@Suppress("ForbiddenComment")
// TODO: Storing complete ViewState into SavedState can lead to TransactionTooLarge crashes. Only data that can't
// be easily recovered, such as user input, should be stored.
private val _viewState = savedState.getStateFlow(
scope = this,
initialValue = ViewState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import com.woocommerce.android.e2e.helpers.InitializationRule
import com.woocommerce.android.e2e.helpers.TestBase
import com.woocommerce.android.e2e.helpers.util.MocksReader
import com.woocommerce.android.e2e.helpers.util.StatsSummaryData
import com.woocommerce.android.e2e.rules.Retry
import com.woocommerce.android.e2e.rules.RetryTestRule
import com.woocommerce.android.e2e.screens.TabNavComponent
import com.woocommerce.android.e2e.screens.login.WelcomeScreen
Expand Down Expand Up @@ -76,7 +75,12 @@ class StatsUITest : TestBase() {
visitors = "12000",
)

@Retry(numberOfTimes = 1)
@Ignore(
"""
This became flaky after the last dashboard changes.
https://github.com/woocommerce/woocommerce-android/issues/12111
"""
)
@Test
fun e2eStatsSummary() {
DashboardScreen()
Expand All @@ -88,7 +92,12 @@ class StatsUITest : TestBase() {
.assertStatsSummary(yearStats)
}

@Retry(numberOfTimes = 1)
@Ignore(
"""
This became flaky after the last dashboard changes.
https://github.com/woocommerce/woocommerce-android/issues/12111
"""
)
@Test
fun e2eStatsTopPerformers() {
val topPerformersJSONArray = MocksReader().readStatsTopPerformersToArray()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class UpdateAnalyticsDashboardRangeSelections @Inject constructor(
getSelectedRangeForTopPerformers.invoke().first().let { add(it) }
getSelectedRangeForDashboardStats.invoke().first().let { add(it) }
}
val forceCardUpdates = listOf(AnalyticsCards.Products, AnalyticsCards.Revenue)
val forceCardUpdates = listOf(AnalyticsCards.Products, AnalyticsCards.Revenue, AnalyticsCards.Session)
return coroutineScope {
val asyncCalls = dashboardRangeSelections.map { selectedRange ->
async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class UpdateDataOnBackgroundWorker @AssistedInject constructor(
@Assisted workerParams: WorkerParameters,
private val accountRepository: AccountRepository,
private val updateAnalyticsDashboardRangeSelections: UpdateAnalyticsDashboardRangeSelections,
private val updateOrdersList: UpdateOrdersList
) : CoroutineWorker(appContext, workerParams) {
companion object {
const val REFRESH_TIME = 4L
Expand All @@ -23,7 +24,7 @@ class UpdateDataOnBackgroundWorker @AssistedInject constructor(
override suspend fun doWork(): Result {
return when {
accountRepository.isUserLoggedIn().not() -> Result.success()
updateAnalyticsDashboardRangeSelections() -> Result.success()
updateAnalyticsDashboardRangeSelections() && updateOrdersList() -> Result.success()
else -> Result.retry()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.woocommerce.android.background

import com.woocommerce.android.ui.orders.filters.domain.GetWCOrderListDescriptorWithFilters
import org.wordpress.android.fluxc.store.ListStore
import org.wordpress.android.fluxc.store.WCOrderStore
import javax.inject.Inject

class UpdateOrdersList @Inject constructor(
private val getWCOrderListDescriptorWithFilters: GetWCOrderListDescriptorWithFilters,
private val listStore: ListStore,
private val ordersStore: WCOrderStore
) {
suspend operator fun invoke(): Boolean {
val listDescriptor = getWCOrderListDescriptorWithFilters()
val response = ordersStore.fetchOrdersListFirstPage(listDescriptor)
val orders = response.model

if (response.isError || orders == null) return false

orders.map { it.orderId }.let { remoteIds ->
listStore.saveListFetched(
listDescriptor = listDescriptor,
remoteItemIds = remoteIds,
canLoadMore = remoteIds.size == listDescriptor.config.networkPageSize
)
}

return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,33 @@ data class AnalyticCardConfiguration(
val isVisible: Boolean = true,
)

enum class AnalyticsCards(val resId: Int, val isPlugin: Boolean = false) {
enum class AnalyticsCards(
val resId: Int,
val isPlugin: Boolean = false
) {
Revenue(R.string.analytics_revenue_card_title),
Orders(R.string.analytics_orders_card_title),
Products(R.string.analytics_products_card_title),
Session(R.string.analytics_session_card_title, isPlugin = true),
Bundles(R.string.analytics_bundles_card_title, isPlugin = true),
GiftCards(R.string.analytics_gift_cards_card_title, isPlugin = true),
GoogleAds(R.string.analytics_google_ads_card_title, isPlugin = true),
GoogleAds(R.string.analytics_google_ads_card_title, isPlugin = true);

/**
* Changing the AnalyticsCard name can cause crashes due to the attachment of the name with
* the Analytics Hub Settings Data Store.
*
* To allow us to update the tracked name without causing issues to the Hub settings storage,
* this field separates the AnalyticsCard definition from the tracked information.
*/
val trackName: String
get() = when (this) {
Revenue -> "revenue"
Orders -> "orders"
Products -> "products"
Session -> "session"
Bundles -> "bundles"
GiftCards -> "giftcards"
GoogleAds -> "googleCampaigns"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ class AnalyticsHubViewModel @Inject constructor(
.run { this as? DeltaPercentage.Value }?.value,
reportUrl = getReportUrl(
selection = ranges,
card = ReportCard.GoogleAds
card = ReportCard.GoogleCampaigns
),
items = googleAdsStats.googleAdsCampaigns.map {
AnalyticsHubListCardItemViewState(
Expand Down Expand Up @@ -776,7 +776,7 @@ class AnalyticsHubViewModel @Inject constructor(
}
}

enum class ReportCard { Revenue, Orders, Products, Bundles, GiftCard, GoogleAds }
enum class ReportCard { Revenue, Orders, Products, Bundles, GiftCard, GoogleCampaigns }

fun AnalyticsCards.toReportCard(): ReportCard? {
return when (this) {
Expand All @@ -785,7 +785,7 @@ fun AnalyticsCards.toReportCard(): ReportCard? {
AnalyticsCards.Products -> ReportCard.Products
AnalyticsCards.Bundles -> ReportCard.Bundles
AnalyticsCards.GiftCards -> ReportCard.GiftCard
AnalyticsCards.GoogleAds -> ReportCard.GoogleAds
AnalyticsCards.GoogleAds -> ReportCard.GoogleCampaigns
else -> null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class GetReportUrl @Inject constructor(
ReportCard.Products -> "path=%2Fanalytics%2Fproducts"
ReportCard.Bundles -> "path=%2Fanalytics%2Fbundles"
ReportCard.GiftCard -> "path=%2Fanalytics%2Fgift-cards"
ReportCard.GoogleAds -> "path=%2Fgoogle%2Freports"
ReportCard.GoogleCampaigns -> "path=%2Fgoogle%2Freports"
}
val period = getPeriod(selection)
val compare = "compare=previous_period"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ class AnalyticsHubSettingsViewModel @Inject constructor(
const val MARKETPLACE = "https://woocommerce.com/products/"
}

/**
* Saving more data than necessary into the SavedState has associated risks which were not known at the time this
* field was implemented - after we ensure we don't save unnecessary data, we can replace @Suppress("OPT_IN_USAGE")
* with @OptIn(LiveDelegateSavedStateAPI::class).
*/
@Suppress("OPT_IN_USAGE")
val viewStateData: LiveDataDelegate<AnalyticsHubSettingsViewState> =
LiveDataDelegate(savedState, AnalyticsHubSettingsViewState.Loading)

Expand Down Expand Up @@ -106,7 +112,7 @@ class AnalyticsHubSettingsViewModel @Inject constructor(
val enabledCards = mutableListOf<String>()
val disabledCards = mutableListOf<String>()
configuration.forEach { cardConfiguration ->
val cardName = cardConfiguration.card.name.lowercase()
val cardName = cardConfiguration.card.trackName
if (cardConfiguration.isVisible) {
enabledCards.add(cardName)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ class UserEligibilityErrorViewModel @Inject constructor(
private const val ROLES_KEY = "current_roles"
}

/**
* Saving more data than necessary into the SavedState has associated risks which were not known at the time this
* field was implemented - after we ensure we don't save unnecessary data, we can replace @Suppress("OPT_IN_USAGE")
* with @OptIn(LiveDelegateSavedStateAPI::class).
*/
@Suppress("OPT_IN_USAGE")
val viewStateData = LiveDataDelegate(savedState, ViewState())
private var viewState by viewStateData

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import com.woocommerce.android.ui.dashboard.reviews.DashboardReviewsCard
import com.woocommerce.android.ui.dashboard.stats.DashboardStatsCard
import com.woocommerce.android.ui.dashboard.stock.DashboardProductStockCard
import com.woocommerce.android.ui.dashboard.topperformers.DashboardTopPerformersWidgetCard
import com.woocommerce.android.util.FeatureFlag

@Composable
fun DashboardContainer(
Expand Down Expand Up @@ -173,11 +172,10 @@ private fun ConfigurableWidgetCard(
)

DashboardWidget.Type.GOOGLE_ADS -> {
if (FeatureFlag.GOOGLE_ADS_M1.isEnabled()) {
DashboardGoogleAdsCard(
modifier = modifier
)
}
DashboardGoogleAdsCard(
parentViewModel = dashboardViewModel,
modifier = modifier
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class DashboardFragment :
}

binding.myStoreRefreshLayout.setOnRefreshListener {
binding.myStoreRefreshLayout.isRefreshing = false
dashboardViewModel.onPullToRefresh()
refreshJitm()
}
Expand Down
Loading

0 comments on commit 2aae80a

Please sign in to comment.