Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,9 @@ dependencies {
testImplementation "org.assertj:assertj-core:3.27.7"
testImplementation "org.robolectric:robolectric:4.16.1"
}

tasks.withType(Test).configureEach {
inputs.file("../src/errors.ts")
.withPropertyName("checkoutErrorCodeWireFormat")
.withPathSensitivity(PathSensitivity.RELATIVE)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.shopify.reactnative.checkoutkit

import com.shopify.checkoutkit.CheckoutErrorCode
import java.io.File
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test

class CheckoutErrorCodeParityTest {

@Test
fun `every android error code is declared in the JavaScript enum`() {
val errorsFile = findErrorsFile()
val declaredCodes = declaredCodesIn(errorsFile)

assertThat(declaredCodes)
.withFailMessage("Found no CheckoutErrorCode members in %s", errorsFile.path)
.isNotEmpty()

val missingCodes = CheckoutErrorCode.values()
.map { it.name.lowercase() }
.filterNot(declaredCodes::contains)

assertThat(missingCodes)
.withFailMessage(
"%s omits %s. Add each code to CheckoutErrorCode there.",
errorsFile.path,
missingCodes,
)
.isEmpty()
}

private fun declaredCodesIn(errorsFile: File): Set<String> =
MEMBER_PATTERN.findAll(errorsFile.readText())
.map { match -> match.groupValues[2] }
.toSet()

private fun findErrorsFile(): File {
val startDirectory = File("").absoluteFile
var directory: File? = startDirectory

while (directory != null) {
val candidate = File(directory, RELATIVE_ERRORS_PATH)
if (candidate.isFile) {
return candidate
}
directory = directory.parentFile
}

throw AssertionError("Found no $RELATIVE_ERRORS_PATH in $startDirectory or any parent directory")
}

private companion object {
const val RELATIVE_ERRORS_PATH = "src/errors.ts"
val MEMBER_PATTERN = Regex("""(\w+) = '([a-z0-9_]+)'""")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,27 +128,16 @@ export { Checkout }

// @public
export enum CheckoutErrorCode {
// (undocumented)
cartCompleted = "cart_completed",
// (undocumented)
cartExpired = "cart_expired",
// (undocumented)
customerAccountRequired = "customer_account_required",
// (undocumented)
httpError = "http_error",
// (undocumented)
invalidCart = "invalid_cart",
// (undocumented)
networkError = "network_error",
// (undocumented)
sdkError = "sdk_error",
// (undocumented)
storefrontPasswordRequired = "storefront_password_required",
// (undocumented)
unknown = "unknown",
// (undocumented)
webContentProcessTerminated = "web_content_process_terminated",
// (undocumented)
webViewNotSupported = "web_view_not_supported"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,47 @@
* The string values are the wire format shared by both native SDKs:
* `CheckoutErrorCode` on iOS sends its `rawValue`, and Android sends
* the lower-snake-case enum constant name.
*
* Every member arrives from both platforms unless its own documentation
* names a single platform.
*/
export enum CheckoutErrorCode {
/** The storefront requires a password and cannot be used by Checkout Kit. */
storefrontPasswordRequired = 'storefront_password_required',

/** Checkout requires a customer account that is not available to the current session. */
customerAccountRequired = 'customer_account_required',

/** The cart or checkout session is no longer available. Create a new cart before retrying. */
cartExpired = 'cart_expired',

/** The cart has already completed checkout. */
cartCompleted = 'cart_completed',

/** The cart is invalid or cannot be used to continue checkout. */
invalidCart = 'invalid_cart',

/** Checkout returned an HTTP error response. See {@link CheckoutException.statusCode}. */
httpError = 'http_error',

/** Checkout navigation failed before an HTTP response was available. */
networkError = 'network_error',

/**
* The installed WebView provider does not support the required WebMessageListener API.
*
* Android only. Android System WebView updates apart from the operating system,
* so an old provider can lack the API. iOS never sends this code.
*/
webViewNotSupported = 'web_view_not_supported',

/** The WebView renderer process terminated or crashed. Reopen checkout to recover. */
webContentProcessTerminated = 'web_content_process_terminated',

/** An internal Checkout Kit error occurred, for example when a protocol message could not be decoded. */
sdkError = 'sdk_error',

/** An unexpected error occurred. */
unknown = 'unknown',
}

Expand Down
Loading