Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save musketyr/c750f00f331070ae7d3e9bab832047d8 to your computer and use it in GitHub Desktop.

Select an option

Save musketyr/c750f00f331070ae7d3e9bab832047d8 to your computer and use it in GitHub Desktop.
Spock to JUnit 5 Migration Diff
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spock → JUnit 5 Migration: GoogleAnalyticsRequestUtilsSpec</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; padding: 20px; line-height: 1.6; }
h1 { text-align: center; margin-bottom: 20px; color: #333; }
.section { background: white; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); overflow: hidden; }
.section-header { background: #2d3748; color: white; padding: 12px 16px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; }
.section-header:hover { background: #4a5568; }
.section-header h2 { font-size: 16px; font-weight: 600; }
.section-header .toggle { font-size: 12px; }
.section-content { display: block; }
.section-content.collapsed { display: none; }
.diff-container { display: grid; grid-template-columns: 1fr 1fr; }
.diff-panel { padding: 16px; overflow-x: auto; }
.diff-panel.left { background: #fff5f5; border-right: 1px solid #e2e8f0; }
.diff-panel.right { background: #f0fff4; }
.diff-panel h3 { font-size: 12px; text-transform: uppercase; color: #718096; margin-bottom: 12px; letter-spacing: 0.5px; }
pre { font-family: 'SF Mono', Monaco, 'Courier New', monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word; }
.left pre { color: #c53030; }
.right pre { color: #276749; }
@media (max-width: 768px) { .diff-container { grid-template-columns: 1fr; } .diff-panel.left { border-right: none; border-bottom: 1px solid #e2e8f0; } }
</style>
</head>
<body>
<h1>🦀 Spock → JUnit 5 Migration: GoogleAnalyticsRequestUtilsSpec</h1>
<p style="text-align: center; color: #666; margin-bottom: 20px;">Story: <a href="https://app.shortcut.com/agorapulse/story/185893">sc185893</a> | PR: <a href="https://github.com/agorapulse/platform/pull/72990">#72990</a></p>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>📦 Imports</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre>package agorapulse.roi.service.google.client.analytics.api
import agorapulse.roi.core.models.Dashboard
import agorapulse.roi.core.models.EventType
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.DimensionName
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.Filter
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.FilterExpression
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.FilterExpressionList
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.InListFilter
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.MetricName
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.Payload
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.StringFilter
import spock.lang.Specification
import java.time.LocalDate</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre>package agorapulse.roi.service.google.client.analytics.api;
import agorapulse.roi.core.models.Dashboard;
import agorapulse.roi.core.models.EventType;
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.DimensionName;
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.Filter;
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.FilterExpression;
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.FilterExpressionList;
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.InListFilter;
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.MetricName;
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.Payload;
import agorapulse.roi.service.google.client.analytics.api.Ga4InsightsApiRequest.StringFilter;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🏗️ Class & Fields</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre>class GoogleAnalyticsRequestUtilsSpec extends Specification {
private static final List&lt;String&gt; CONVERSION_EVENT_NAMES = [&#x27;one&#x27;, &#x27;session_start&#x27;]
</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre>class GoogleAnalyticsRequestUtilsTest {
private static final List&lt;String&gt; CONVERSION_EVENT_NAMES = List.of(&quot;one&quot;, &quot;session_start&quot;);
</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should get event filters - custom event</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should get event filters - custom event&#x27;() {
given:
EventType eventType = EventType.CUSTOM_EVENT
Dashboard.Goal event = new Dashboard.Goal(&#x27;test&#x27;, &#x27;test&#x27;, false)
when:
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, event, [])
then:
filters == [
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&#x27;test&#x27;)
.build()
]
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldGetEventFiltersForCustomEvent() {
// given
EventType eventType = EventType.CUSTOM_EVENT;
Dashboard.Goal event = new Dashboard.Goal(&quot;test&quot;, &quot;test&quot;, false);
// when
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, event, List.of());
// then
assertThat(filters).containsExactly(
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&quot;test&quot;)
.build()
);
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should get event filters - all conversion events</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should get event filters - all conversion events&#x27;() {
given:
EventType eventType = EventType.ALL_CONVERSION_EVENTS
when:
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, null, [])
then:
filters == [
DimensionFilter.builder()
.dimensionType(DimensionType.IS_CONVERSION_EVENT)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&#x27;true&#x27;)
.build()
]
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldGetEventFiltersForAllConversionEvents() {
// given
EventType eventType = EventType.ALL_CONVERSION_EVENTS;
// when
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, null, List.of());
// then
assertThat(filters).containsExactly(
DimensionFilter.builder()
.dimensionType(DimensionType.IS_CONVERSION_EVENT)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&quot;true&quot;)
.build()
);
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should get event filters - all events</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should get event filters - all events&#x27;() {
given:
EventType eventType = EventType.ALL_EVENTS
when:
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, null, [])
then:
filters == [
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.notExpressionEnabled(true)
.dimensionMatchType(DimensionMatchType.IN_LIST)
.values([&#x27;user_engagement&#x27;])
.build()
]
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldGetEventFiltersForAllEvents() {
// given
EventType eventType = EventType.ALL_EVENTS;
// when
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, null, List.of());
// then
assertThat(filters).containsExactly(
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.notExpressionEnabled(true)
.dimensionMatchType(DimensionMatchType.IN_LIST)
.values(List.of(&quot;user_engagement&quot;))
.build()
);
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should get event filters - all events except excluded events</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should get event filters - all events except excluded events&#x27;() {
given:
EventType eventType = EventType.ALL_EVENTS
when:
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, null, [&#x27;purchase&#x27;])
then:
filters == [
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.notExpressionEnabled(true)
.dimensionMatchType(DimensionMatchType.IN_LIST)
.values([&#x27;user_engagement&#x27;, &#x27;purchase&#x27;])
.build()
]
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldGetEventFiltersForAllEventsExceptExcludedEvents() {
// given
EventType eventType = EventType.ALL_EVENTS;
// when
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, null, List.of(&quot;purchase&quot;));
// then
assertThat(filters).containsExactly(
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.notExpressionEnabled(true)
.dimensionMatchType(DimensionMatchType.IN_LIST)
.values(List.of(&quot;user_engagement&quot;, &quot;purchase&quot;))
.build()
);
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should get event filters - purchase event</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should get event filters - purchase event&#x27;() {
given:
EventType eventType = EventType.PURCHASE
when:
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, null, [])
then:
filters == [
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&#x27;purchase&#x27;)
.build()
]
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldGetEventFiltersForPurchaseEvent() {
// given
EventType eventType = EventType.PURCHASE;
// when
List&lt;DimensionFilter&gt; filters = GoogleAnalyticsRequestUtils.getEventFilters(eventType, CONVERSION_EVENT_NAMES, null, List.of());
// then
assertThat(filters).containsExactly(
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&quot;purchase&quot;)
.build()
);
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should initialize events request</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should initialize events request&#x27;() {
given:
LocalDate startDate = LocalDate.parse(&#x27;2023-01-01&#x27;)
LocalDate endDate = LocalDate.parse(&#x27;2023-01-31&#x27;)
String accessToken = &#x27;testAccessToken&#x27;
String dashboardId = &#x27;test&#x27;
List&lt;DimensionFilter&gt; filters = [
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&#x27;purchase&#x27;)
.build()]
when:
Ga4InsightsApiRequest request = GoogleAnalyticsRequestUtils.initEventsRequest(startDate, endDate, accessToken, dashboardId, filters, null)
then:
request.accessToken == accessToken
request.propertyId == &#x27;properties/&#x27; + dashboardId
request.payload.dateRanges.first().startDate == startDate
request.payload.dateRanges.first().endDate == endDate
request.payload.dimensionFilter == FilterExpression.builder()
.andGroup(new FilterExpressionList([
FilterExpression.builder()
.filter(Filter.builder()
.fieldName(&#x27;eventName&#x27;)
.stringFilter(new StringFilter(&#x27;EXACT&#x27;, &#x27;purchase&#x27;))
.build())
.build()]))
.build()
request.payload.keepEmptyRows
request.payload.limit == GoogleAnalyticsRequestUtils.DEFAULT_RESULT_LIMIT
request.payload.metrics.size() == 4
request.payload.metrics.containsAll([
new MetricName(MetricType.CONVERSION_GOAL_COMPLETIONS.ga4Code),
new MetricName(MetricType.GENERATED_REVENUE_GOAL_VALUE.ga4Code),
new MetricName(MetricType.GENERATED_REVENUE_TRANSACTIONS.ga4Code),
])
request.payload.metricAggregations.first() == &#x27;TOTAL&#x27;
request.payload.offset == 0
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldInitializeEventsRequest() {
// given
LocalDate startDate = LocalDate.parse(&quot;2023-01-01&quot;);
LocalDate endDate = LocalDate.parse(&quot;2023-01-31&quot;);
String accessToken = &quot;testAccessToken&quot;;
String dashboardId = &quot;test&quot;;
List&lt;DimensionFilter&gt; filters = List.of(
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&quot;purchase&quot;)
.build()
);
// when
Ga4InsightsApiRequest request = GoogleAnalyticsRequestUtils.initEventsRequest(startDate, endDate, accessToken, dashboardId, filters, null);
// then
assertThat(request.getAccessToken()).isEqualTo(accessToken);
assertThat(request.getPropertyId()).isEqualTo(&quot;properties/&quot; + dashboardId);
assertThat(request.getPayload().getDateRanges().get(0).getStartDate()).isEqualTo(startDate);
assertThat(request.getPayload().getDateRanges().get(0).getEndDate()).isEqualTo(endDate);
assertThat(request.getPayload().getDimensionFilter()).isEqualTo(
FilterExpression.builder()
.andGroup(new FilterExpressionList(List.of(
FilterExpression.builder()
.filter(Filter.builder()
.fieldName(&quot;eventName&quot;)
.stringFilter(new StringFilter(&quot;EXACT&quot;, &quot;purchase&quot;))
.build())
.build()
)))
.build()
);
assertThat(request.getPayload().getKeepEmptyRows()).isTrue();
assertThat(request.getPayload().getLimit()).isEqualTo(GoogleAnalyticsRequestUtils.DEFAULT_RESULT_LIMIT);
assertThat(request.getPayload().getMetrics()).hasSize(4);
assertThat(request.getPayload().getMetrics()).contains(
new MetricName(MetricType.CONVERSION_GOAL_COMPLETIONS.getGa4Code()),
new MetricName(MetricType.GENERATED_REVENUE_GOAL_VALUE.getGa4Code()),
new MetricName(MetricType.GENERATED_REVENUE_TRANSACTIONS.getGa4Code())
);
assertThat(request.getPayload().getMetricAggregations().get(0)).isEqualTo(&quot;TOTAL&quot;);
assertThat(request.getPayload().getOffset()).isEqualTo(0);
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should initialize Visitor request</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should initialize Visitor request&#x27;() {
given:
LocalDate startDate = LocalDate.parse(&#x27;2023-01-01&#x27;)
LocalDate endDate = LocalDate.parse(&#x27;2023-01-31&#x27;)
String accessToken = &#x27;testAccessToken&#x27;
String dashboardId = &#x27;test&#x27;
when:
Ga4InsightsApiRequest request = GoogleAnalyticsRequestUtils.initVisitorRequest(startDate, endDate, accessToken, dashboardId, [], null)
then:
request.accessToken == accessToken
request.propertyId == &#x27;properties/&#x27; + dashboardId
request.payload.dateRanges.first().startDate == startDate
request.payload.dateRanges.first().endDate == endDate
request.payload.dimensionFilter == FilterExpression.builder().andGroup(new FilterExpressionList([])).build()
request.payload.keepEmptyRows
request.payload.limit == GoogleAnalyticsRequestUtils.DEFAULT_RESULT_LIMIT
request.payload.metrics.size() == 1
request.payload.metrics == [new MetricName(MetricType.VISITOR.ga4Code)]
request.payload.metricAggregations.first() == &#x27;TOTAL&#x27;
request.payload.offset == 0
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldInitializeVisitorRequest() {
// given
LocalDate startDate = LocalDate.parse(&quot;2023-01-01&quot;);
LocalDate endDate = LocalDate.parse(&quot;2023-01-31&quot;);
String accessToken = &quot;testAccessToken&quot;;
String dashboardId = &quot;test&quot;;
// when
Ga4InsightsApiRequest request = GoogleAnalyticsRequestUtils.initVisitorRequest(startDate, endDate, accessToken, dashboardId, List.of(), null);
// then
assertThat(request.getAccessToken()).isEqualTo(accessToken);
assertThat(request.getPropertyId()).isEqualTo(&quot;properties/&quot; + dashboardId);
assertThat(request.getPayload().getDateRanges().get(0).getStartDate()).isEqualTo(startDate);
assertThat(request.getPayload().getDateRanges().get(0).getEndDate()).isEqualTo(endDate);
assertThat(request.getPayload().getDimensionFilter()).isEqualTo(
FilterExpression.builder().andGroup(new FilterExpressionList(List.of())).build()
);
assertThat(request.getPayload().getKeepEmptyRows()).isTrue();
assertThat(request.getPayload().getLimit()).isEqualTo(GoogleAnalyticsRequestUtils.DEFAULT_RESULT_LIMIT);
assertThat(request.getPayload().getMetrics()).hasSize(1);
assertThat(request.getPayload().getMetrics()).containsExactly(new MetricName(MetricType.VISITOR.getGa4Code()));
assertThat(request.getPayload().getMetricAggregations().get(0)).isEqualTo(&quot;TOTAL&quot;);
assertThat(request.getPayload().getOffset()).isEqualTo(0);
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should initialize Events request - complex filters</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should initialize Events request - complex filters&#x27;() {
given:
LocalDate startDate = LocalDate.parse(&#x27;2023-01-01&#x27;)
LocalDate endDate = LocalDate.parse(&#x27;2023-01-31&#x27;)
String accessToken = &#x27;testAccessToken&#x27;
String dashboardId = &#x27;test&#x27;
List&lt;DimensionFilter&gt; filters = [
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.notExpressionEnabled(true)
.dimensionMatchType(DimensionMatchType.IN_LIST)
.values([&#x27;session_start&#x27;, &#x27;user_engagement&#x27;])
.build(),
DimensionFilter.builder()
.dimensionType(DimensionType.CHANNEL_GROUPING)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&#x27;Organic Social&#x27;)
.build(),
]
when:
Ga4InsightsApiRequest request = GoogleAnalyticsRequestUtils.initEventsRequest(startDate, endDate, accessToken, dashboardId, filters, null)
then:
request.payload.dimensionFilter == FilterExpression.builder()
.andGroup(new FilterExpressionList([
FilterExpression.builder()
.notExpression(FilterExpression.builder()
.filter(Filter.builder()
.fieldName(&#x27;eventName&#x27;)
.inListFilter(new InListFilter([&#x27;session_start&#x27;, &#x27;user_engagement&#x27;]))
.build())
.build())
.build(),
FilterExpression.builder()
.filter(Filter.builder()
.fieldName(&#x27;sessionDefaultChannelGroup&#x27;)
.stringFilter(new StringFilter(&#x27;EXACT&#x27;, &#x27;Organic Social&#x27;))
.build())
.build(),
]))
.build()
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldInitializeEventsRequestWithComplexFilters() {
// given
LocalDate startDate = LocalDate.parse(&quot;2023-01-01&quot;);
LocalDate endDate = LocalDate.parse(&quot;2023-01-31&quot;);
String accessToken = &quot;testAccessToken&quot;;
String dashboardId = &quot;test&quot;;
List&lt;DimensionFilter&gt; filters = List.of(
DimensionFilter.builder()
.dimensionType(DimensionType.EVENT_NAME)
.notExpressionEnabled(true)
.dimensionMatchType(DimensionMatchType.IN_LIST)
.values(List.of(&quot;session_start&quot;, &quot;user_engagement&quot;))
.build(),
DimensionFilter.builder()
.dimensionType(DimensionType.CHANNEL_GROUPING)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&quot;Organic Social&quot;)
.build()
);
// when
Ga4InsightsApiRequest request = GoogleAnalyticsRequestUtils.initEventsRequest(startDate, endDate, accessToken, dashboardId, filters, null);
// then
assertThat(request.getPayload().getDimensionFilter()).isEqualTo(
FilterExpression.builder()
.andGroup(new FilterExpressionList(List.of(
FilterExpression.builder()
.notExpression(FilterExpression.builder()
.filter(Filter.builder()
.fieldName(&quot;eventName&quot;)
.inListFilter(new InListFilter(List.of(&quot;session_start&quot;, &quot;user_engagement&quot;)))
.build())
.build())
.build(),
FilterExpression.builder()
.filter(Filter.builder()
.fieldName(&quot;sessionDefaultChannelGroup&quot;)
.stringFilter(new StringFilter(&quot;EXACT&quot;, &quot;Organic Social&quot;))
.build())
.build()
)))
.build()
);
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should add orderBy to request with transactions conversion - visitors</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should add orderBy to request with transactions conversion - visitors&#x27;() {
given:
Payload payload = Payload.builder().metrics([new MetricName(MetricType.VISITOR.ga4Code)]).build()
when:
GoogleAnalyticsRequestUtils.addOrderBy(payload, EventType.PURCHASE, MetricType.VISITOR.ga4Code, true)
then:
payload.orderBys.size() == 1
payload.orderBys[0].metric.metricName == MetricType.VISITOR.ga4Code
payload.orderBys[0].desc
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldAddOrderByToRequestWithTransactionsConversionForVisitors() {
// given
Payload payload = Payload.builder().metrics(List.of(new MetricName(MetricType.VISITOR.getGa4Code()))).build();
// when
GoogleAnalyticsRequestUtils.addOrderBy(payload, EventType.PURCHASE, MetricType.VISITOR.getGa4Code(), true);
// then
assertThat(payload.getOrderBys()).hasSize(1);
assertThat(payload.getOrderBys().get(0).getMetric().getMetricName()).isEqualTo(MetricType.VISITOR.getGa4Code());
assertThat(payload.getOrderBys().get(0).getDesc()).isTrue();
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should add orderBy to request with transactions conversion - events</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should add orderBy to request with transactions conversion - events&#x27;() {
given:
Payload payload = Payload.builder()
.metrics(MetricType.values().findAll { metric -&gt; metric != MetricType.VISITOR }.collect { metric -&gt; new MetricName(metric.ga4Code) })
.build()
when:
GoogleAnalyticsRequestUtils.addOrderBy(payload, EventType.PURCHASE, MetricType.VISITOR.ga4Code, true)
then:
payload.orderBys.size() == 2
payload.orderBys[0].metric.metricName == MetricType.CONVERSION_TRANSACTIONS.ga4Code
payload.orderBys[0].desc
payload.orderBys[1].metric.metricName == MetricType.GENERATED_REVENUE_TRANSACTIONS.ga4Code
payload.orderBys[1].desc
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldAddOrderByToRequestWithTransactionsConversionForEvents() {
// given
List&lt;MetricName&gt; metrics = java.util.Arrays.stream(MetricType.values())
.filter(metric -&gt; metric != MetricType.VISITOR)
.map(metric -&gt; new MetricName(metric.getGa4Code()))
.toList();
Payload payload = Payload.builder().metrics(metrics).build();
// when
GoogleAnalyticsRequestUtils.addOrderBy(payload, EventType.PURCHASE, MetricType.VISITOR.getGa4Code(), true);
// then
assertThat(payload.getOrderBys()).hasSize(2);
assertThat(payload.getOrderBys().get(0).getMetric().getMetricName()).isEqualTo(MetricType.CONVERSION_TRANSACTIONS.getGa4Code());
assertThat(payload.getOrderBys().get(0).getDesc()).isTrue();
assertThat(payload.getOrderBys().get(1).getMetric().getMetricName()).isEqualTo(MetricType.GENERATED_REVENUE_TRANSACTIONS.getGa4Code());
assertThat(payload.getOrderBys().get(1).getDesc()).isTrue();
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should add orderBy to request with goal conversion - visitors</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should add orderBy to request with goal conversion - visitors&#x27;() {
given:
Payload payload = Payload.builder().metrics([new MetricName(MetricType.VISITOR.ga4Code)]).build()
when:
GoogleAnalyticsRequestUtils.addOrderBy(payload, EventType.ALL_EVENTS, MetricType.CONVERSION_GOAL_COMPLETIONS.ga4Code, false)
then:
payload.orderBys.size() == 1
payload.orderBys[0].metric.metricName == MetricType.VISITOR.ga4Code
!payload.orderBys[0].desc
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldAddOrderByToRequestWithGoalConversionForVisitors() {
// given
Payload payload = Payload.builder().metrics(List.of(new MetricName(MetricType.VISITOR.getGa4Code()))).build();
// when
GoogleAnalyticsRequestUtils.addOrderBy(payload, EventType.ALL_EVENTS, MetricType.CONVERSION_GOAL_COMPLETIONS.getGa4Code(), false);
// then
assertThat(payload.getOrderBys()).hasSize(1);
assertThat(payload.getOrderBys().get(0).getMetric().getMetricName()).isEqualTo(MetricType.VISITOR.getGa4Code());
assertThat(payload.getOrderBys().get(0).getDesc()).isFalse();
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should add orderBy to request with goal conversion - events</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should add orderBy to request with goal conversion - events&#x27;() {
given:
Payload payload = Payload.builder()
.metrics(MetricType.values().findAll { metric -&gt; metric != MetricType.VISITOR }.collect { metric -&gt; new MetricName(metric.ga4Code) })
.build()
when:
GoogleAnalyticsRequestUtils.addOrderBy(payload, EventType.ALL_EVENTS, MetricType.CONVERSION_GOAL_COMPLETIONS.ga4Code, false)
then:
payload.orderBys.size() == 2
payload.orderBys[0].metric.metricName == MetricType.CONVERSION_GOAL_COMPLETIONS.ga4Code
!payload.orderBys[0].desc
payload.orderBys[1].metric.metricName == MetricType.GENERATED_REVENUE_GOAL_VALUE.ga4Code
!payload.orderBys[1].desc
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldAddOrderByToRequestWithGoalConversionForEvents() {
// given
List&lt;MetricName&gt; metrics = java.util.Arrays.stream(MetricType.values())
.filter(metric -&gt; metric != MetricType.VISITOR)
.map(metric -&gt; new MetricName(metric.getGa4Code()))
.toList();
Payload payload = Payload.builder().metrics(metrics).build();
// when
GoogleAnalyticsRequestUtils.addOrderBy(payload, EventType.ALL_EVENTS, MetricType.CONVERSION_GOAL_COMPLETIONS.getGa4Code(), false);
// then
assertThat(payload.getOrderBys()).hasSize(2);
assertThat(payload.getOrderBys().get(0).getMetric().getMetricName()).isEqualTo(MetricType.CONVERSION_GOAL_COMPLETIONS.getGa4Code());
assertThat(payload.getOrderBys().get(0).getDesc()).isFalse();
assertThat(payload.getOrderBys().get(1).getMetric().getMetricName()).isEqualTo(MetricType.GENERATED_REVENUE_GOAL_VALUE.getGa4Code());
assertThat(payload.getOrderBys().get(1).getDesc()).isFalse();
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should finalize request with dimensions and dimension filters</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should finalize request with dimensions and dimension filters&#x27;() {
given:
FilterExpression filter = FilterExpression.builder()
.filter(Filter.builder()
.fieldName(DimensionType.EVENT_NAME.ga4Code)
.stringFilter(new StringFilter(DimensionMatchType.EXACT.name(), &#x27;purchase&#x27;))
.build())
.build()
FilterExpression newAddedFilter = FilterExpression.builder()
.filter(Filter.builder()
.fieldName(DimensionType.CHANNEL_GROUPING.ga4Code)
.stringFilter(new StringFilter(DimensionMatchType.EXACT.name(), &#x27;Organic Social&#x27;))
.build())
.build()
Payload payload = Payload.builder().dimensionFilter(FilterExpression.builder().andGroup(new FilterExpressionList([filter])).build()).build()
when:
GoogleAnalyticsRequestUtils.finalizeRequest(
payload,
[DimensionType.CHANNEL_GROUPING, DimensionType.DATE],
[DimensionFilter.builder()
.dimensionType(DimensionType.CHANNEL_GROUPING)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&#x27;Organic Social&#x27;)
.build()])
then:
payload.dimensions.size() == 2
payload.dimensions.containsAll([
new DimensionName(DimensionType.CHANNEL_GROUPING.ga4Code),
new DimensionName(DimensionType.DATE.ga4Code)])
payload.dimensionFilter.andGroup.expressions.size() == 2
payload.dimensionFilter.andGroup.expressions.containsAll(filter, newAddedFilter)
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldFinalizeRequestWithDimensionsAndDimensionFilters() {
// given
FilterExpression filter = FilterExpression.builder()
.filter(Filter.builder()
.fieldName(DimensionType.EVENT_NAME.getGa4Code())
.stringFilter(new StringFilter(DimensionMatchType.EXACT.name(), &quot;purchase&quot;))
.build())
.build();
FilterExpression newAddedFilter = FilterExpression.builder()
.filter(Filter.builder()
.fieldName(DimensionType.CHANNEL_GROUPING.getGa4Code())
.stringFilter(new StringFilter(DimensionMatchType.EXACT.name(), &quot;Organic Social&quot;))
.build())
.build();
Payload payload = Payload.builder()
.dimensionFilter(FilterExpression.builder().andGroup(new FilterExpressionList(List.of(filter))).build())
.build();
// when
GoogleAnalyticsRequestUtils.finalizeRequest(
payload,
List.of(DimensionType.CHANNEL_GROUPING, DimensionType.DATE),
List.of(DimensionFilter.builder()
.dimensionType(DimensionType.CHANNEL_GROUPING)
.dimensionMatchType(DimensionMatchType.EXACT)
.value(&quot;Organic Social&quot;)
.build())
);
// then
assertThat(payload.getDimensions()).hasSize(2);
assertThat(payload.getDimensions()).contains(
new DimensionName(DimensionType.CHANNEL_GROUPING.getGa4Code()),
new DimensionName(DimensionType.DATE.getGa4Code())
);
assertThat(payload.getDimensionFilter().getAndGroup().getExpressions()).hasSize(2);
assertThat(payload.getDimensionFilter().getAndGroup().getExpressions()).contains(filter, newAddedFilter);
}</pre>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Should finalize request with dimensions and no filters</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre> void &#x27;Should finalize request with dimensions and no filters&#x27;() {
given:
Payload payload = Payload.builder().dimensionFilter(FilterExpression.builder().andGroup(new FilterExpressionList([])).build()).build()
when:
GoogleAnalyticsRequestUtils.finalizeRequest(
payload,
[DimensionType.CHANNEL_GROUPING, DimensionType.DATE],
[]
)
then:
payload.dimensions.size() == 2
payload.dimensions.containsAll([
new DimensionName(DimensionType.CHANNEL_GROUPING.ga4Code),
new DimensionName(DimensionType.DATE.ga4Code)])
payload.dimensionFilter == null
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre> @Test
void shouldFinalizeRequestWithDimensionsAndNoFilters() {
// given
Payload payload = Payload.builder()
.dimensionFilter(FilterExpression.builder().andGroup(new FilterExpressionList(List.of())).build())
.build();
// when
GoogleAnalyticsRequestUtils.finalizeRequest(
payload,
List.of(DimensionType.CHANNEL_GROUPING, DimensionType.DATE),
List.of()
);
// then
assertThat(payload.getDimensions()).hasSize(2);
assertThat(payload.getDimensions()).contains(
new DimensionName(DimensionType.CHANNEL_GROUPING.getGa4Code()),
new DimensionName(DimensionType.DATE.getGa4Code())
);
assertThat(payload.getDimensionFilter()).isNull();
}</pre>
</div>
</div>
</div>
</div>
<script>
function toggleSection(header) {
const content = header.nextElementSibling;
const toggle = header.querySelector('.toggle');
content.classList.toggle('collapsed');
toggle.textContent = content.classList.contains('collapsed') ? '▶' : '▼';
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment