From f6bac5297bbce0920f34981717ee1f14c511ae71 Mon Sep 17 00:00:00 2001 From: jianglai Date: Wed, 15 May 2019 08:44:56 -0700 Subject: [PATCH] Add Google Analytics to registrar console To support the open source community, which may want to use different analytics services, we implement a soy template for analytics services that: 1) Does not require users to implement Google Analytics 2) Allows users to add their own analytics code to `Analytics.soy` 3) Gives users the flexibility to pass as much or as little static configuration to their custom analytics code as needed. 4) Ensures that users can merge upstream Nomulus code in the future without having to delete their custom analytics implementations 5) Does not allow code to be injected from configuration, which Soy as a framework actively discourages. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=248340081 --- .../registry/config/RegistryConfig.java | 19 +++++++++++ .../config/RegistryConfigSettings.java | 6 ++++ .../registry/config/files/default-config.yaml | 5 +++ .../registrar/ConsoleOteSetupAction.java | 4 +++ .../ConsoleRegistrarCreatorAction.java | 4 +++ .../ui/server/registrar/ConsoleUiAction.java | 8 +++-- java/google/registry/ui/soy/Analytics.soy | 34 +++++++++++++++++++ java/google/registry/ui/soy/Console.soy | 4 ++- .../registry/ui/soy/registrar/Console.soy | 6 ++++ .../ui/soy/registrar/OteSetupConsole.soy | 9 +++++ .../soy/registrar/RegistrarCreateConsole.soy | 7 ++++ .../ui/js/registrar/console_test_util.js | 4 +++ .../registrar/ConsoleOteSetupActionTest.java | 6 ++++ .../ConsoleRegistrarCreatorActionTest.java | 8 +++++ .../server/registrar/ConsoleUiActionTest.java | 14 ++++++++ 15 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 java/google/registry/ui/soy/Analytics.soy diff --git a/java/google/registry/config/RegistryConfig.java b/java/google/registry/config/RegistryConfig.java index 3ce45e672..8cd655142 100644 --- a/java/google/registry/config/RegistryConfig.java +++ b/java/google/registry/config/RegistryConfig.java @@ -35,6 +35,9 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.net.URI; import java.net.URL; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import javax.annotation.Nullable; @@ -198,6 +201,22 @@ public final class RegistryConfig { return config.registrarConsole.technicalDocsUrl; } + /** + * Configuration for analytics services installed in the web console. + * + * @see google.registry.ui.server.registrar.ConsoleUiAction + * @see google.registry.ui.soy.AnalyticsSoyInfo + */ + @Provides + @Config("analyticsConfig") + public static Map provideAnalyticsConfig(RegistryConfigSettings config) { + // Can't be an ImmutableMap because it may contain null values. + HashMap analyticsConfig = new HashMap<>(); + analyticsConfig.put( + "googleAnalyticsId", config.registrarConsole.analyticsConfig.googleAnalyticsId); + return Collections.unmodifiableMap(analyticsConfig); + } + /** * Returns the Google Cloud Storage bucket for storing zone files. * diff --git a/java/google/registry/config/RegistryConfigSettings.java b/java/google/registry/config/RegistryConfigSettings.java index dda79a8c8..a6894627e 100644 --- a/java/google/registry/config/RegistryConfigSettings.java +++ b/java/google/registry/config/RegistryConfigSettings.java @@ -154,6 +154,12 @@ public class RegistryConfigSettings { public String announcementsEmailAddress; public String integrationEmailAddress; public String technicalDocsUrl; + public AnalyticsConfig analyticsConfig; + } + + /** Configuration for analytics services installed in the registrar console */ + public static class AnalyticsConfig { + public String googleAnalyticsId; } /** Configuration for monitoring. */ diff --git a/java/google/registry/config/files/default-config.yaml b/java/google/registry/config/files/default-config.yaml index 8aa53a12f..61e7fa617 100644 --- a/java/google/registry/config/files/default-config.yaml +++ b/java/google/registry/config/files/default-config.yaml @@ -332,6 +332,11 @@ registrarConsole: # URL linking to directory of technical support docs on the registry. technicalDocsUrl: http://example.com/your_support_docs/ + # Configuration for all analytics services installed in the web console + analyticsConfig: + # Google Analytics account where data on console use is sent, optional + googleAnalyticsId: null + monitoring: # Max queries per second for the Google Cloud Monitoring V3 (aka Stackdriver) # API. The limit can be adjusted by contacting Cloud Support. diff --git a/java/google/registry/ui/server/registrar/ConsoleOteSetupAction.java b/java/google/registry/ui/server/registrar/ConsoleOteSetupAction.java index 7a1a36be3..02ed0b235 100644 --- a/java/google/registry/ui/server/registrar/ConsoleOteSetupAction.java +++ b/java/google/registry/ui/server/registrar/ConsoleOteSetupAction.java @@ -48,6 +48,7 @@ import google.registry.ui.server.SoyTemplateUtils; import google.registry.ui.soy.registrar.OteSetupConsoleSoyInfo; import google.registry.util.StringGenerator; import java.util.HashMap; +import java.util.Map; import java.util.Optional; import javax.inject.Inject; import javax.inject.Named; @@ -79,6 +80,7 @@ public final class ConsoleOteSetupAction implements Runnable { SoyTemplateUtils.createTofuSupplier( google.registry.ui.soy.ConsoleSoyInfo.getInstance(), google.registry.ui.soy.FormsSoyInfo.getInstance(), + google.registry.ui.soy.AnalyticsSoyInfo.getInstance(), google.registry.ui.soy.registrar.OteSetupConsoleSoyInfo.getInstance()); @VisibleForTesting // webdriver and screenshot tests need this @@ -98,6 +100,7 @@ public final class ConsoleOteSetupAction implements Runnable { @Inject SendEmailUtils sendEmailUtils; @Inject @Config("logoFilename") String logoFilename; @Inject @Config("productName") String productName; + @Inject @Config("analyticsConfig") Map analyticsConfig; @Inject @Named("base58StringGenerator") StringGenerator passwordGenerator; @Inject @Parameter("clientId") Optional clientId; @Inject @Parameter("email") Optional email; @@ -140,6 +143,7 @@ public final class ConsoleOteSetupAction implements Runnable { data.put("username", user.getNickname()); data.put("logoutUrl", userService.createLogoutURL(PATH)); data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail())); + data.put("analyticsConfig", analyticsConfig); response.setContentType(MediaType.HTML_UTF_8); if (!registrarAccessor.isAdmin()) { diff --git a/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java b/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java index 6328d92d3..4e423b2ac 100644 --- a/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java +++ b/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java @@ -56,6 +56,7 @@ import google.registry.ui.server.SoyTemplateUtils; import google.registry.ui.soy.registrar.RegistrarCreateConsoleSoyInfo; import google.registry.util.StringGenerator; import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.stream.Stream; import javax.inject.Inject; @@ -90,6 +91,7 @@ public final class ConsoleRegistrarCreatorAction implements Runnable { SoyTemplateUtils.createTofuSupplier( google.registry.ui.soy.ConsoleSoyInfo.getInstance(), google.registry.ui.soy.FormsSoyInfo.getInstance(), + google.registry.ui.soy.AnalyticsSoyInfo.getInstance(), google.registry.ui.soy.registrar.RegistrarCreateConsoleSoyInfo.getInstance()); @VisibleForTesting // webdriver and screenshot tests need this @@ -109,6 +111,7 @@ public final class ConsoleRegistrarCreatorAction implements Runnable { @Inject SendEmailUtils sendEmailUtils; @Inject @Config("logoFilename") String logoFilename; @Inject @Config("productName") String productName; + @Inject @Config("analyticsConfig") Map analyticsConfig; @Inject @Named("base58StringGenerator") StringGenerator passwordGenerator; @Inject @Named("digitOnlyStringGenerator") StringGenerator passcodeGenerator; @Inject @Parameter("clientId") Optional clientId; @@ -167,6 +170,7 @@ public final class ConsoleRegistrarCreatorAction implements Runnable { data.put("username", user.getNickname()); data.put("logoutUrl", userService.createLogoutURL(PATH)); data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail())); + data.put("analyticsConfig", analyticsConfig); response.setContentType(MediaType.HTML_UTF_8); if (!registrarAccessor.isAdmin()) { diff --git a/java/google/registry/ui/server/registrar/ConsoleUiAction.java b/java/google/registry/ui/server/registrar/ConsoleUiAction.java index 7bdf601b1..b5883972c 100644 --- a/java/google/registry/ui/server/registrar/ConsoleUiAction.java +++ b/java/google/registry/ui/server/registrar/ConsoleUiAction.java @@ -47,6 +47,7 @@ import google.registry.request.auth.AuthenticatedRegistrarAccessor.Role; import google.registry.security.XsrfTokenManager; import google.registry.ui.server.SoyTemplateUtils; import google.registry.ui.soy.registrar.ConsoleSoyInfo; +import java.util.Map; import java.util.Optional; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; @@ -62,7 +63,8 @@ public final class ConsoleUiAction implements Runnable { private static final Supplier TOFU_SUPPLIER = SoyTemplateUtils.createTofuSupplier( google.registry.ui.soy.ConsoleSoyInfo.getInstance(), - google.registry.ui.soy.registrar.ConsoleSoyInfo.getInstance()); + google.registry.ui.soy.registrar.ConsoleSoyInfo.getInstance(), + google.registry.ui.soy.AnalyticsSoyInfo.getInstance()); @VisibleForTesting // webdriver and screenshot tests need this public static final Supplier CSS_RENAMING_MAP_SUPPLIER = @@ -86,6 +88,7 @@ public final class ConsoleUiAction implements Runnable { @Inject @Config("supportPhoneNumber") String supportPhoneNumber; @Inject @Config("technicalDocsUrl") String technicalDocsUrl; @Inject @Config("registrarConsoleEnabled") boolean enabled; + @Inject @Config("analyticsConfig") Map analyticsConfig; @Inject @Parameter(PARAM_CLIENT_ID) Optional paramClientId; @Inject ConsoleUiAction() {} @@ -120,6 +123,7 @@ public final class ConsoleUiAction implements Runnable { data.put("announcementsEmail", announcementsEmail); data.put("supportPhoneNumber", supportPhoneNumber); data.put("technicalDocsUrl", technicalDocsUrl); + data.put("analyticsConfig", analyticsConfig); if (!enabled) { response.setStatus(SC_SERVICE_UNAVAILABLE); response.setPayload( @@ -136,7 +140,7 @@ public final class ConsoleUiAction implements Runnable { ImmutableSetMultimap roleMap = registrarAccessor.getAllClientIdWithRoles(); data.put("allClientIds", roleMap.keySet()); data.put("environment", environment.toString()); - // We set the initual value to the value that will show if guessClientId throws. + // We set the initial value to the value that will show if guessClientId throws. String clientId = ""; try { clientId = paramClientId.orElse(registrarAccessor.guessClientId()); diff --git a/java/google/registry/ui/soy/Analytics.soy b/java/google/registry/ui/soy/Analytics.soy new file mode 100644 index 000000000..341a59792 --- /dev/null +++ b/java/google/registry/ui/soy/Analytics.soy @@ -0,0 +1,34 @@ +// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +{namespace registry.soy.analytics} + +/** + * The JS template required to install Google Analytics for the registrar console. + */ +{template .googleAnalytics} + {@param analyticsConfig: [googleAnalyticsId: string|null]} + {let $id: $analyticsConfig.googleAnalyticsId /} + + {if $id} + + + + {/if} +{/template} + diff --git a/java/google/registry/ui/soy/Console.soy b/java/google/registry/ui/soy/Console.soy index b1082d436..09a66c962 100644 --- a/java/google/registry/ui/soy/Console.soy +++ b/java/google/registry/ui/soy/Console.soy @@ -21,7 +21,8 @@ {template .header} {@param app: string} /** App identifier, e.g. 'admin', 'registrar'. */ {@param? subtitle: string} /** Extra stuff to put in {@code }. */ - <!doctype html> + {@param analyticsConfig: [googleAnalyticsId: string|null]} + <!doctype html> <meta charset="utf-8"> {literal}<!-- @@ -56,6 +57,7 @@ <!-- No DEBUG option set. --> {/switch} <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Open+Sans:300"> + {call registry.soy.analytics.googleAnalytics data="all" /} {/template} diff --git a/java/google/registry/ui/soy/registrar/Console.soy b/java/google/registry/ui/soy/registrar/Console.soy index acf83b3d5..2edb0aabc 100644 --- a/java/google/registry/ui/soy/registrar/Console.soy +++ b/java/google/registry/ui/soy/registrar/Console.soy @@ -35,10 +35,12 @@ {@param supportPhoneNumber: string} {@param technicalDocsUrl: string} {@param environment: string} + {@param analyticsConfig: [googleAnalyticsId: string|null]} {call registry.soy.console.header} {param app: 'registrar' /} {param subtitle: 'Registrar Console' /} + {param analyticsConfig: $analyticsConfig /} {/call} {call registry.soy.console.googlebar data="all" /} <div id="reg-app"> @@ -145,9 +147,11 @@ {template .disabled} {@param logoFilename: string} {@param productName: string} + {@param analyticsConfig: [googleAnalyticsId: string|null]} {call registry.soy.console.header} {param app: 'registrar' /} {param subtitle: 'Console Disabled' /} + {param analyticsConfig: $analyticsConfig /} {/call} <div class="{css('whoAreYou-disabled')}"> <a class="{css('logo')}" href="/registrar"> @@ -172,9 +176,11 @@ {@param logoFilename: string} {@param productName: string} {@param? clientId: string} + {@param analyticsConfig: [googleAnalyticsId: string|null]} {call registry.soy.console.header} {param app: 'registrar' /} {param subtitle: 'Not Authorized' /} + {param analyticsConfig: $analyticsConfig /} {/call} <div class="{css('whoAreYou')}"> <a class="{css('logo')}" href="/registrar"> diff --git a/java/google/registry/ui/soy/registrar/OteSetupConsole.soy b/java/google/registry/ui/soy/registrar/OteSetupConsole.soy index e1cc3315f..03da925ca 100644 --- a/java/google/registry/ui/soy/registrar/OteSetupConsole.soy +++ b/java/google/registry/ui/soy/registrar/OteSetupConsole.soy @@ -23,6 +23,8 @@ {@param username: string} /** Arbitrary username to display. */ {@param logoutUrl: string} /** Generated URL for logging out of Google. */ {@param productName: string} /** Name to display for this software product. */ + {@param analyticsConfig: [googleAnalyticsId: string|null]} + {@param logoFilename: string} {@param? errorMessage: string} /** If set - display the error message above the form. */ {@param? baseClientId: string} /** If set - an initial value to fill for the base client ID. */ @@ -31,6 +33,7 @@ {call registry.soy.console.header} {param app: 'registrar' /} {param subtitle: 'OT&E setup' /} + {param analyticsConfig: $analyticsConfig /} {/call} {call registry.soy.console.googlebar data="all" /} <div id="reg-content-and-footer"> @@ -58,10 +61,12 @@ {@param logoutUrl: string} /** Generated URL for logging out of Google. */ {@param productName: string} /** Name to display for this software product. */ {@param logoFilename: string} + {@param analyticsConfig: [googleAnalyticsId: string|null]} {call registry.soy.console.header} {param app: 'registrar' /} {param subtitle: 'OT&E setup' /} + {param analyticsConfig: $analyticsConfig /} {/call} {call registry.soy.console.googlebar data="all" /} <div id="reg-content-and-footer"> @@ -100,6 +105,7 @@ {@param xsrfToken: string} /** Security token. */ {@param? baseClientId: string} /** If set - an initial value to fill for the base client ID. */ {@param? contactEmail: string} /** If set - an initial value to fill for the email. */ + <form name="item" class="{css('item')}" method="post" action="/registrar-ote-setup"> <table> <tr class="{css('kd-settings-pane-section')}"> @@ -162,9 +168,12 @@ {@param logoutUrl: string} /** Generated URL for logging out of Google. */ {@param logoFilename: string} {@param productName: string} + {@param analyticsConfig: [googleAnalyticsId: string|null]} + {call registry.soy.console.header} {param app: 'registrar' /} {param subtitle: 'Not Authorized' /} + {param analyticsConfig: $analyticsConfig /} {/call} <div class="{css('whoAreYou')}"> <a class="{css('logo')}" href="/registrar"> diff --git a/java/google/registry/ui/soy/registrar/RegistrarCreateConsole.soy b/java/google/registry/ui/soy/registrar/RegistrarCreateConsole.soy index a0b3e7445..74d966908 100644 --- a/java/google/registry/ui/soy/registrar/RegistrarCreateConsole.soy +++ b/java/google/registry/ui/soy/registrar/RegistrarCreateConsole.soy @@ -24,6 +24,7 @@ {@param logoutUrl: string} /** Generated URL for logging out of Google. */ {@param productName: string} /** Name to display for this software product. */ {@param logoFilename: string} + {@param analyticsConfig: [googleAnalyticsId: string|null]} {@param? errorMessage: string} /** If set - display the error message above the form. */ {@param? clientId: string} /** If set - an initial value for the client ID. */ {@param? name: string} /** If set - an initial value for the Registrar name. */ @@ -43,6 +44,7 @@ {call registry.soy.console.header} {param app: 'registrar' /} {param subtitle: 'Create Registrar' /} + {param analyticsConfig: $analyticsConfig /} {/call} {call registry.soy.console.googlebar data="all" /} <div id="reg-content-and-footer"> @@ -70,10 +72,12 @@ {@param logoutUrl: string} /** Generated URL for logging out of Google. */ {@param productName: string} /** Name to display for this software product. */ {@param logoFilename: string} + {@param analyticsConfig: [googleAnalyticsId: string|null]} {call registry.soy.console.header} {param app: 'registrar' /} {param subtitle: 'Create Registrar' /} + {param analyticsConfig: $analyticsConfig /} {/call} {call registry.soy.console.googlebar data="all" /} <div id="reg-content-and-footer"> @@ -335,9 +339,12 @@ {@param logoutUrl: string} /** Generated URL for logging out of Google. */ {@param logoFilename: string} {@param productName: string} + {@param analyticsConfig: [googleAnalyticsId: string|null]} + {call registry.soy.console.header} {param app: 'registrar' /} {param subtitle: 'Not Authorized' /} + {param analyticsConfig: $analyticsConfig /} {/call} <div class="{css('whoAreYou')}"> <a class="{css('logo')}" href="/registrar"> diff --git a/javatests/google/registry/ui/js/registrar/console_test_util.js b/javatests/google/registry/ui/js/registrar/console_test_util.js index ed30ca33a..53a287119 100644 --- a/javatests/google/registry/ui/js/registrar/console_test_util.js +++ b/javatests/google/registry/ui/js/registrar/console_test_util.js @@ -61,6 +61,7 @@ registry.registrar.ConsoleTestUtil.renderConsoleMain = function( supportPhoneNumber: args.supportPhoneNumber || '+1 (888) 555 0123', technicalDocsUrl: args.technicalDocsUrl || 'http://example.com/techdocs', environment: args.environment || 'UNITTEST', + analyticsConfig: args.analyticsConfig || {googleAnalyticsId: null}, }); }; @@ -80,6 +81,9 @@ registry.registrar.ConsoleTestUtil.visit = function( opt_args.clientId = opt_args.clientId || 'dummyRegistrarId'; opt_args.xsrfToken = opt_args.xsrfToken || 'dummyXsrfToken'; opt_args.isAdmin = !!opt_args.isAdmin; + opt_args.analyticsConfig = + opt_args.analyticsConfig || {googleAnalyticsIds: null}; + // set the default isOwner to be the opposite of isAdmin. // That way, if we don't explicitly state them both we get what we'd expect: // {} -> OWNER (the "regular" case of a visitor to the console) diff --git a/javatests/google/registry/ui/server/registrar/ConsoleOteSetupActionTest.java b/javatests/google/registry/ui/server/registrar/ConsoleOteSetupActionTest.java index 939d1bca8..45c2c72d6 100644 --- a/javatests/google/registry/ui/server/registrar/ConsoleOteSetupActionTest.java +++ b/javatests/google/registry/ui/server/registrar/ConsoleOteSetupActionTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.when; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserServiceFactory; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSetMultimap; import google.registry.config.RegistryEnvironment; import google.registry.model.registry.Registry; @@ -97,6 +98,7 @@ public final class ConsoleOteSetupActionTest { action.productName = "Nomulus"; action.clientId = Optional.empty(); action.email = Optional.empty(); + action.analyticsConfig = ImmutableMap.of("googleAnalyticsId", "sampleId"); action.optionalPassword = Optional.empty(); action.passwordGenerator = new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz"); @@ -115,6 +117,7 @@ public final class ConsoleOteSetupActionTest { public void testGet_authorized() { action.run(); assertThat(response.getPayload()).contains("<h1>Setup OT&E</h1>"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); } @Test @@ -129,6 +132,7 @@ public final class ConsoleOteSetupActionTest { AuthenticatedRegistrarAccessor.createForTesting(ImmutableSetMultimap.of()); action.run(); assertThat(response.getPayload()).contains("<h1>You need permission</h1>"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); } @Test @@ -160,6 +164,7 @@ public final class ConsoleOteSetupActionTest { + " Registrar myclientid-4 with access to TLD myclientid-ga\n" + " Registrar myclientid-5 with access to TLD myclientid-eap\n" + "Gave user contact@registry.example web access to these Registrars\n"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); } @Test @@ -189,5 +194,6 @@ public final class ConsoleOteSetupActionTest { action.method = Method.POST; action.run(); assertThat(response.getPayload()).contains("<h1>You need permission</h1>"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); } } diff --git a/javatests/google/registry/ui/server/registrar/ConsoleRegistrarCreatorActionTest.java b/javatests/google/registry/ui/server/registrar/ConsoleRegistrarCreatorActionTest.java index a08278d23..2a9d15a8d 100644 --- a/javatests/google/registry/ui/server/registrar/ConsoleRegistrarCreatorActionTest.java +++ b/javatests/google/registry/ui/server/registrar/ConsoleRegistrarCreatorActionTest.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.when; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserServiceFactory; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSetMultimap; import google.registry.config.RegistryEnvironment; import google.registry.model.registrar.Registrar; @@ -119,6 +120,8 @@ public final class ConsoleRegistrarCreatorActionTest { action.passwordGenerator = new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz"); action.passcodeGenerator = new DeterministicStringGenerator("314159265"); + + action.analyticsConfig = ImmutableMap.of("googleAnalyticsId", "sampleId"); } @Test @@ -134,6 +137,7 @@ public final class ConsoleRegistrarCreatorActionTest { public void testGet_authorized() { action.run(); assertThat(response.getPayload()).contains("<h1>Create Registrar</h1>"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); } @Test @@ -141,6 +145,7 @@ public final class ConsoleRegistrarCreatorActionTest { action.registryEnvironment = RegistryEnvironment.PRODUCTION; action.run(); assertThat(response.getPayload()).contains("<h1>Create Registrar</h1>"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); } @Test @@ -149,6 +154,7 @@ public final class ConsoleRegistrarCreatorActionTest { AuthenticatedRegistrarAccessor.createForTesting(ImmutableSetMultimap.of()); action.run(); assertThat(response.getPayload()).contains("<h1>You need permission</h1>"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); } @Test @@ -243,6 +249,7 @@ public final class ConsoleRegistrarCreatorActionTest { assertThat(response.getPayload()) .contains("<h1>Successfully created Registrar myclientid</h1>"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); Registrar registrar = loadByClientId("myclientid").orElse(null); assertThat(registrar).isNotNull(); @@ -414,5 +421,6 @@ public final class ConsoleRegistrarCreatorActionTest { action.method = Method.POST; action.run(); assertThat(response.getPayload()).contains("<h1>You need permission</h1>"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); } } diff --git a/javatests/google/registry/ui/server/registrar/ConsoleUiActionTest.java b/javatests/google/registry/ui/server/registrar/ConsoleUiActionTest.java index 02ac263f7..059048444 100644 --- a/javatests/google/registry/ui/server/registrar/ConsoleUiActionTest.java +++ b/javatests/google/registry/ui/server/registrar/ConsoleUiActionTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.when; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserServiceFactory; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.net.MediaType; import google.registry.config.RegistryEnvironment; @@ -79,6 +80,7 @@ public class ConsoleUiActionTest { action.paramClientId = Optional.empty(); action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false)); action.environment = RegistryEnvironment.UNITTEST; + action.analyticsConfig = ImmutableMap.of("googleAnalyticsId", "sampleId"); action.registrarAccessor = AuthenticatedRegistrarAccessor.createForTesting( @@ -122,6 +124,13 @@ public class ConsoleUiActionTest { assertMetric("TheRegistrar", "false", "[OWNER]", "SUCCESS"); } + @Test + public void testWebPage_containsGoogleAnalyticsId() { + action.run(); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); + assertMetric("TheRegistrar", "false", "[OWNER]", "SUCCESS"); + } + @Test public void testUserHasAccessAsTheRegistrar_showsRegistrarConsole() { action.run(); @@ -135,6 +144,7 @@ public class ConsoleUiActionTest { action.enabled = false; action.run(); assertThat(response.getPayload()).contains("<h1>Console is disabled</h1>"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); } @Test @@ -144,6 +154,7 @@ public class ConsoleUiActionTest { action.run(); assertThat(response.getPayload()).contains("<h1>You need permission</h1>"); assertThat(response.getPayload()).contains("not associated with Nomulus."); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); assertMetric("<null>", "false", "[]", "FORBIDDEN"); } @@ -172,6 +183,7 @@ public class ConsoleUiActionTest { action.run(); assertThat(response.getPayload()).contains("<h1>You need permission</h1>"); assertThat(response.getPayload()).contains("not associated with the registrar fakeRegistrar."); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); assertMetric("fakeRegistrar", "true", "[]", "FORBIDDEN"); } @@ -181,6 +193,7 @@ public class ConsoleUiActionTest { action.run(); assertThat(response.getPayload()).contains("Registrar Console"); assertThat(response.getPayload()).contains("reg-content-and-footer"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); assertMetric("NewRegistrar", "true", "[OWNER, ADMIN]", "SUCCESS"); } @@ -190,6 +203,7 @@ public class ConsoleUiActionTest { assertThat(response.getPayload()).contains("<option value=\"TheRegistrar\" selected>"); assertThat(response.getPayload()).contains("<option value=\"NewRegistrar\">"); assertThat(response.getPayload()).contains("<option value=\"AdminRegistrar\">"); + assertThat(response.getPayload()).contains("gtag('config', 'sampleId')"); assertMetric("TheRegistrar", "false", "[OWNER]", "SUCCESS"); } }