diff --git a/src/global-methods.js b/src/global-methods.js index 85338ba0..37a41112 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -1,14 +1,36 @@ import axios from "axios"; +import analyticsMixIn from "@/mixins/analytics-mixin.js"; + import { applicationConfig } from "@/constants/application-config.js"; +import { GaCategories, GaActions, GaLabels } from "@/constants/analytics"; export default { - callHttpClient({ method, endpoint, payload}) { + callHttpClient({ method, endpoint, payload, logApiCall = true}) { return new Promise((resolve, reject) => { const cfDistroUrl = applicationConfig.CONSUMER_CF_DISTRO; const payloadAndAnalyticsData = Object.assign({}, payload, { AppName: "SelfService" }); + const headers = { + [headerKeys.EXPERIMENT]: JSON.stringify(store.getters.experimentSettings), + }; - axios({ method: method, url: cfDistroUrl + endpoint, data: payloadAndAnalyticsData, crossDomain: true, responseType: {}}) + axios({ + method: method, + url: cfDistroUrl + endpoint, + data: payloadAndAnalyticsData, + crossDomain: true, + responseType: {}, + headers: headers, + }) .then((response) => { + if (logApiCall) { + analyticsMixIn.methods.pushEventToGA( + GaCategories.API_RESPONSE, + GaActions.RESULT, + `${GaLabels.SUCCESS}_${endpoint}`, + true + ); + } + return resolve(response); }, error => { @@ -22,7 +44,12 @@ export default { //used for mocked services async mockCallHttpClient(method, endpoint) { return new Promise((resolve, reject) => { - axios({ method: method, url: endpoint, crossDomain: true, responseType: {}}) + axios({ + method: method, + url: endpoint, + crossDomain: true, + responseType: {} + }) .then((response) => { return resolve(response); }, diff --git a/src/global-methods.spec.js b/src/global-methods.spec.js index 286fe976..c0f63da2 100644 --- a/src/global-methods.spec.js +++ b/src/global-methods.spec.js @@ -1,8 +1,10 @@ import axios from 'axios'; import globalMethods from "@/global-methods"; +import analyticsMixIn from "@/mixins/analytics-mixin"; //Mock external dependencies jest.mock("axios"); +jest.mock("@/mixins/analytics-mixin"); it("Global Methods - Call Http Client - Should Resolve Promise", () => { //Arrange @@ -25,6 +27,7 @@ it("Global Methods - Call Http Client - Should Resolve Promise", () => { endpoint: endpoint, isError: true, }); + analyticsMixIn.methods.pushEventToGA = jest.fn(); //Act globalMethods.callHttpClient(httpArgs).catch((err) => { diff --git a/src/main.js b/src/main.js index 3361fe54..50932e83 100644 --- a/src/main.js +++ b/src/main.js @@ -5,9 +5,12 @@ import "../node_modules/bootstrap/dist/js/bootstrap.js"; import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; import { useMainStore } from '@/store'; import baseMixin from "@/mixins/base-mixin.js"; +import analyticsMixin from "@/mixins/analytics-mixin.js"; +import experimentMixin from "@/mixins/experiment-mixin.js"; import { createPinia } from 'pinia'; import Maska from "maska"; +// Vue App Setup const vueApp = createApp(App); // Pinia @@ -20,10 +23,7 @@ useMainStore().populateInitialState(); vueApp.mixin(baseMixin); vueApp.use(Maska); vueApp.use(router); +vueApp.mixin(analyticsMixin); +vueApp.mixin(experimentMixin); + vueApp.mount("#app"); - - - - - - diff --git a/src/mixins/experiment-mixin.js b/src/mixins/experiment-mixin.js new file mode 100644 index 00000000..11b57368 --- /dev/null +++ b/src/mixins/experiment-mixin.js @@ -0,0 +1,17 @@ +import store from "@/store"; + +export default { + methods: { + hasSettingEqualTo(settingName, settingValue) { + return store.getters.experimentSettings[settingName] == settingValue; + }, + hasSetting(settingName) { + return Object.hasOwn(store.getters.experimentSettings, settingName); + }, + getSettingValue(settingName) { + return this.hasSetting(settingName) + ? store.getters.experimentSettings[settingName] + : null; + }, + }, +}; diff --git a/src/mixins/experiment-mixin.spec.js b/src/mixins/experiment-mixin.spec.js new file mode 100644 index 00000000..1b2bff2f --- /dev/null +++ b/src/mixins/experiment-mixin.spec.js @@ -0,0 +1,148 @@ +import experimentMixin from "@/mixins/experiment-mixin"; +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import store from "@/store"; + +describe("experiment-mixin", () => { + describe("hasSettingEqualTo", () => { + test("setting exists and value matches => return true", () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const result = wrapper.vm.hasSettingEqualTo("Setting2", "Value2"); + + // Assert + expect(result).toEqual(true); + }); + + test("setting exists and value does not match => return false", () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const result = wrapper.vm.hasSettingEqualTo("Setting2", "Value3"); + + // Assert + expect(result).toEqual(false); + }); + + test("setting does not exist => return false", () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const result = wrapper.vm.hasSettingEqualTo("SettingBoogly", "Woogly"); + + // Assert + expect(result).toEqual(false); + }); + + test("there are no settings => return false", () => { + // Arrange + const { wrapper } = setupMocks({ experimentSettings: {} }); + + // Act + const result = wrapper.vm.hasSettingEqualTo("Setting2", "Value3"); + + // Assert + expect(result).toEqual(false); + }); + }); + + describe("hasSetting", () => { + test("has setting => return true", () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const result = wrapper.vm.hasSetting("Setting4"); + + // Assert + expect(result).toEqual(true); + }); + + test("does not have setting => return false", () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const result = wrapper.vm.hasSetting("BooglyWoogly"); + + // Assert + expect(result).toEqual(false); + }); + + test("experimentSettings is empty => return false", () => { + // Arrange + const { wrapper } = setupMocks({ experimentSettings: {} }); + + // Act + const result = wrapper.vm.hasSetting("Setting4"); + + // Assert + expect(result).toEqual(false); + }); + }); + + describe("getSettingValue", () => { + test("has setting => return correct value", () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const result = wrapper.vm.getSettingValue("Setting3"); + + // Assert + expect(result).toEqual("Value3"); + }); + + test("does not have setting => return null", () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const result = wrapper.vm.getSettingValue("Hello"); + + // Assert + expect(result).toBeNull(); + }); + + test("experimentSettings is empty => return null", () => { + // Arrange + const { wrapper } = setupMocks({ experimentSettings: {} }); + + // Act + const result = wrapper.vm.getSettingValue("Hello"); + + // Assert + expect(result).toBeNull(); + }); + }); +}); + +function setupMocks({ experimentSettings }) { + const mocks = getMountOptions({}); + + const testExperimentSettings = { + Setting1: "Value1", + Setting2: "Value2", + Setting3: "Value3", + Setting4: "Value1", + Setting5: "Value2", + Setting6: "Value3", + }; + + store.getters = { + experimentSettings: experimentSettings ?? testExperimentSettings, + }; + + const mockComponent = { + template: "
", + mixins: [experimentMixin], + }; + + const wrapper = shallowMount(mockComponent, mocks); + + return { wrapper }; +}