Skip to content

Commit f2e9226

Browse files
Add unit tests
1 parent 4092176 commit f2e9226

File tree

1 file changed

+330
-0
lines changed

1 file changed

+330
-0
lines changed
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
package org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings
2+
3+
import kotlinx.coroutines.test.runTest
4+
import org.assertj.core.api.Assertions.assertThat
5+
import org.junit.Test
6+
import org.mockito.kotlin.any
7+
import org.mockito.kotlin.given
8+
import org.mockito.kotlin.mock
9+
import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId
10+
import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId
11+
import org.wordpress.android.fluxc.model.WCProductModel
12+
import org.wordpress.android.fluxc.persistence.dao.ProductsDao
13+
import org.wordpress.android.fluxc.persistence.entity.BookingEntity
14+
import org.wordpress.android.fluxc.persistence.entity.OrderEntity
15+
import java.math.BigDecimal
16+
import java.time.Instant
17+
18+
class BookingDtoMapperTest {
19+
private val productsDao: ProductsDao = mock()
20+
private val localSiteId = LocalId(123)
21+
private val mapper = BookingDtoMapper(productsDao)
22+
23+
@Test
24+
fun `given valid booking dto, when mapping to entity, then all fields are correctly mapped`() = runTest {
25+
// Given
26+
val bookingDto = createSampleBookingDto()
27+
28+
// When
29+
val result = with(mapper) { bookingDto.toEntity(localSiteId, null) }
30+
31+
// Then
32+
assertThat(result.id).isEqualTo(RemoteId(1L))
33+
assertThat(result.localSiteId).isEqualTo(localSiteId)
34+
assertThat(result.start).isEqualTo(Instant.ofEpochSecond(1609459200L)) // 2021-01-01 00:00:00
35+
assertThat(result.end).isEqualTo(Instant.ofEpochSecond(1609462800L)) // 2021-01-01 01:00:00
36+
assertThat(result.allDay).isEqualTo(false)
37+
assertThat(result.status).isEqualTo(BookingEntity.Status.Confirmed)
38+
assertThat(result.cost).isEqualTo("50.00")
39+
assertThat(result.currency).isEqualTo("USD")
40+
assertThat(result.customerId).isEqualTo(456L)
41+
assertThat(result.productId).isEqualTo(789L)
42+
assertThat(result.resourceId).isEqualTo(101L)
43+
assertThat(result.dateCreated).isEqualTo(Instant.ofEpochSecond(1609455600L))
44+
assertThat(result.dateModified).isEqualTo(Instant.ofEpochSecond(1609459200L))
45+
assertThat(result.googleCalendarEventId).isEqualTo("cal-123")
46+
assertThat(result.orderId).isEqualTo(999L)
47+
assertThat(result.orderItemId).isEqualTo(111L)
48+
assertThat(result.parentId).isEqualTo(0L)
49+
assertThat(result.personCounts).containsExactly(2L, 1L)
50+
assertThat(result.localTimezone).isEqualTo("America/New_York")
51+
assertThat(result.order.productInfo).isNull()
52+
}
53+
54+
@Test
55+
fun `given booking dto with null person counts, when mapping, then person counts is null`() = runTest {
56+
// Given
57+
val bookingDto = createSampleBookingDto(personCounts = null)
58+
59+
// When
60+
val result = with(mapper) { bookingDto.toEntity(localSiteId, null) }
61+
62+
// Then
63+
assertThat(result.personCounts).isNull()
64+
}
65+
66+
@Test
67+
fun `given booking dto with empty person counts, when mapping, then person counts is empty`() = runTest {
68+
// Given
69+
val bookingDto = createSampleBookingDto(personCounts = emptyList())
70+
71+
// When
72+
val result = with(mapper) { bookingDto.toEntity(localSiteId, null) }
73+
74+
// Then
75+
assertThat(result.personCounts).isEmpty()
76+
}
77+
78+
@Test
79+
fun `given booking dto with unknown status, when mapping, then status is Unknown`() = runTest {
80+
// Given
81+
val bookingDto = createSampleBookingDto(status = "unknown-status")
82+
83+
// When
84+
val result = with(mapper) { bookingDto.toEntity(localSiteId, null) }
85+
86+
// Then
87+
assertThat(result.status).isInstanceOf(BookingEntity.Status.Unknown::class.java)
88+
assertThat(result.status.key).isEqualTo("unknown-status")
89+
}
90+
91+
@Test
92+
fun `given booking dto with all valid statuses, when mapping, then correct status enum is returned`() = runTest {
93+
val statusMappings = mapOf(
94+
"unpaid" to BookingEntity.Status.Unpaid,
95+
"pending-confirmation" to BookingEntity.Status.PendingConfirmation,
96+
"confirmed" to BookingEntity.Status.Confirmed,
97+
"paid" to BookingEntity.Status.Paid,
98+
"cancelled" to BookingEntity.Status.Cancelled,
99+
"complete" to BookingEntity.Status.Complete
100+
)
101+
102+
statusMappings.forEach { (statusKey, expectedStatus) ->
103+
// Given
104+
val bookingDto = createSampleBookingDto(status = statusKey)
105+
106+
// When
107+
val result = with(mapper) { bookingDto.toEntity(localSiteId, null) }
108+
109+
// Then
110+
assertThat(result.status).isEqualTo(expectedStatus)
111+
}
112+
}
113+
114+
@Test
115+
fun `given booking dto with order entity, when mapping, then order info is populated from order`() = runTest {
116+
// Given
117+
val bookingDto = createSampleBookingDto()
118+
val orderEntity = createSampleOrderEntity()
119+
120+
// When
121+
val result = with(mapper) { bookingDto.toEntity(localSiteId, orderEntity) }
122+
123+
// Then
124+
with(result.order) {
125+
assertThat(status).isEqualTo("processing")
126+
assertThat(productInfo?.name).isEqualTo("Test Product")
127+
assertThat(customerInfo?.billingFirstName).isEqualTo("John")
128+
assertThat(customerInfo?.billingLastName).isEqualTo("Doe")
129+
assertThat(customerInfo?.billingEmail).isEqualTo("[email protected]")
130+
assertThat(customerInfo?.billingCompany).isNull() // empty string becomes null
131+
assertThat(customerInfo?.billingAddress1).isEqualTo("123 Main St")
132+
assertThat(paymentInfo?.subtotal).isEqualTo(BigDecimal("40.00"))
133+
assertThat(paymentInfo?.total).isEqualTo(BigDecimal("50.00"))
134+
}
135+
}
136+
137+
@Test
138+
fun `given booking dto without order entity and product exists, when mapping, then order info has product name`() =
139+
runTest {
140+
// Given
141+
val bookingDto = createSampleBookingDto()
142+
val productModel = WCProductModel(name = "Test Product from DB")
143+
given(productsDao.getProduct(localSiteId.value, bookingDto.productId)).willReturn(productModel)
144+
145+
// When
146+
val result = with(mapper) { bookingDto.toEntity(localSiteId, null) }
147+
148+
// Then
149+
assertThat(result.order.productInfo?.name).isEqualTo("Test Product from DB")
150+
assertThat(result.order.status).isNull()
151+
assertThat(result.order.customerInfo).isNull()
152+
assertThat(result.order.paymentInfo).isNull()
153+
}
154+
155+
@Test
156+
fun `given booking dto without order entity and no product, when mapping, then order info has null product info`() =
157+
runTest {
158+
// Given
159+
val bookingDto = createSampleBookingDto()
160+
given(productsDao.getProduct(any<Int>(), any<Long>())).willReturn(null)
161+
162+
// When
163+
val result = with(mapper) { bookingDto.toEntity(localSiteId, null) }
164+
165+
// Then
166+
assertThat(result.order.productInfo).isNull()
167+
assertThat(result.order.status).isNull()
168+
assertThat(result.order.customerInfo).isNull()
169+
assertThat(result.order.paymentInfo).isNull()
170+
}
171+
172+
@Test
173+
fun `given order entity with empty billing fields, when mapping, then empty strings become null`() = runTest {
174+
// Given
175+
val bookingDto = createSampleBookingDto()
176+
val orderEntity = createSampleOrderEntity().copy(
177+
billingCompany = "",
178+
billingAddress2 = "",
179+
billingCity = "",
180+
billingState = "",
181+
billingPostcode = "",
182+
billingCountry = "",
183+
billingPhone = ""
184+
)
185+
186+
// When
187+
val result = with(mapper) { bookingDto.toEntity(localSiteId, orderEntity) }
188+
189+
// Then
190+
with(result.order.customerInfo!!) {
191+
assertThat(billingCompany).isNull()
192+
assertThat(billingAddress2).isNull()
193+
assertThat(billingCity).isNull()
194+
assertThat(billingState).isNull()
195+
assertThat(billingPostcode).isNull()
196+
assertThat(billingCountry).isNull()
197+
assertThat(billingPhone).isNull()
198+
}
199+
}
200+
201+
@Test
202+
fun `given order entity with no matching line item, when mapping, then payment info is null`() = runTest {
203+
// Given
204+
val bookingDto = createSampleBookingDto(orderItemId = 999L) // non-matching ID
205+
val orderEntity = createSampleOrderEntity()
206+
207+
// When
208+
val result = with(mapper) { bookingDto.toEntity(localSiteId, orderEntity) }
209+
210+
// Then
211+
assertThat(result.order.paymentInfo).isNull()
212+
}
213+
214+
@Test
215+
fun `given order entity with line item having invalid amounts, when mapping, then defaults to zero`() = runTest {
216+
// Given
217+
val bookingDto = createSampleBookingDto()
218+
val orderEntity = createSampleOrderEntity().copy(
219+
lineItems = "[{\"id\":111,\"name\":\"Test Product\",\"subtotal\":\"invalid\",\"total\":\"also-invalid\",\"subtotal_tax\":null,\"total_tax\":\"\"}]"
220+
)
221+
222+
// When
223+
val result = with(mapper) { bookingDto.toEntity(localSiteId, orderEntity) }
224+
225+
// Then
226+
with(result.order.paymentInfo!!) {
227+
assertThat(subtotal).isEqualTo(BigDecimal.ZERO)
228+
assertThat(total).isEqualTo(BigDecimal.ZERO)
229+
assertThat(subtotalTax).isEqualTo(BigDecimal.ZERO)
230+
assertThat(totalTax).isEqualTo(BigDecimal.ZERO)
231+
}
232+
}
233+
234+
private fun createSampleBookingDto(
235+
id: Long = 1L,
236+
start: Long = 1609459200L, // 2021-01-01 00:00:00
237+
end: Long = 1609462800L, // 2021-01-01 01:00:00
238+
allDay: Boolean = false,
239+
status: String = "confirmed",
240+
cost: String = "50.00",
241+
currency: String = "USD",
242+
customerId: Long = 456L,
243+
productId: Long = 789L,
244+
resourceId: Long = 101L,
245+
dateCreated: Long = 1609455600L,
246+
dateModified: Long = 1609459200L,
247+
googleCalendarEventId: String = "cal-123",
248+
orderId: Long = 999L,
249+
orderItemId: Long = 111L,
250+
parentId: Long = 0L,
251+
personCounts: List<Int>? = listOf(2, 1),
252+
localTimezone: String = "America/New_York"
253+
) = BookingDto(
254+
id = id,
255+
start = start,
256+
end = end,
257+
allDay = allDay,
258+
status = status,
259+
cost = cost,
260+
currency = currency,
261+
customerId = customerId,
262+
productId = productId,
263+
resourceId = resourceId,
264+
dateCreated = dateCreated,
265+
dateModified = dateModified,
266+
googleCalendarEventId = googleCalendarEventId,
267+
orderId = orderId,
268+
orderItemId = orderItemId,
269+
parentId = parentId,
270+
personCounts = personCounts,
271+
localTimezone = localTimezone
272+
)
273+
274+
private fun createSampleOrderEntity() = OrderEntity(
275+
localSiteId = localSiteId,
276+
orderId = 999L,
277+
number = "1001",
278+
status = "processing",
279+
currency = "USD",
280+
orderKey = "",
281+
dateCreated = "",
282+
dateModified = "",
283+
total = "50.00",
284+
totalTax = "",
285+
shippingTotal = "",
286+
paymentMethod = "",
287+
paymentMethodTitle = "",
288+
datePaid = "",
289+
pricesIncludeTax = false,
290+
customerNote = "",
291+
discountTotal = "",
292+
discountCodes = "",
293+
customerId = 456L,
294+
billingFirstName = "John",
295+
billingLastName = "Doe",
296+
billingCompany = "",
297+
billingAddress1 = "123 Main St",
298+
billingAddress2 = "Apt 1",
299+
billingCity = "New York",
300+
billingState = "NY",
301+
billingPostcode = "10001",
302+
billingCountry = "US",
303+
billingEmail = "[email protected]",
304+
billingPhone = "555-1234",
305+
shippingFirstName = "",
306+
shippingLastName = "",
307+
shippingCompany = "",
308+
shippingAddress1 = "",
309+
shippingAddress2 = "",
310+
shippingCity = "",
311+
shippingState = "",
312+
shippingPostcode = "",
313+
shippingCountry = "",
314+
shippingPhone = "",
315+
lineItems = "[{\"id\":111,\"name\":\"Test Product\",\"subtotal\":\"40.00\",\"subtotal_tax\":\"5.00\",\"total\":\"50.00\",\"total_tax\":\"7.50\"}]",
316+
shippingLines = "[]",
317+
feeLines = "[]",
318+
taxLines = "[]",
319+
couponLines = "[]",
320+
metaData = emptyList(),
321+
paymentUrl = "",
322+
isEditable = true,
323+
needsPayment = null,
324+
needsProcessing = null,
325+
giftCardCode = "",
326+
giftCardAmount = "",
327+
shippingTax = "",
328+
createdVia = ""
329+
)
330+
}

0 commit comments

Comments
 (0)