diff --git a/src/constants/payment-method-constants.js b/src/constants/payment-method-constants.js
new file mode 100644
index 00000000..0799f2b2
--- /dev/null
+++ b/src/constants/payment-method-constants.js
@@ -0,0 +1,7 @@
+export const paymentMethods = {
+ NONE: null,
+ LATER: "Later",
+ CREDIT_CARD: "CreditCard",
+ PAYPAL: "Paypal",
+ AFTERPAY: "Afterpay",
+};
diff --git a/src/iss-components/nav-bar/nav-bar.spec.js b/src/iss-components/nav-bar/nav-bar.spec.js
new file mode 100644
index 00000000..68b9f6c8
--- /dev/null
+++ b/src/iss-components/nav-bar/nav-bar.spec.js
@@ -0,0 +1,59 @@
+import { mount } from "@vue/test-utils";
+import navbar from "./nav-bar";
+
+describe("nav-bar.vue", () => {
+ test("Should emit ForwardClicked on button click", async () => {
+ // Act
+ const wrapper = mount(navbar, {
+ mixins: [mockMixin],
+ });
+ wrapper.vm.buttonClick();
+ // Assert
+ expect(wrapper.emitted()["ForwardClicked"][0]).toHaveBeenCalled;
+ });
+
+ test("Should emit BackClicked on link click", async () => {
+ // Act
+ const wrapper = mount(navbar, {
+ mixins: [mockMixin],
+ });
+ wrapper.vm.linkClick();
+ // Assert
+ expect(wrapper.emitted()["BackClicked"][0]).toHaveBeenCalled;
+ });
+
+ test("Should change button text when update button text is called", async () => {
+ // Act
+ const wrapper = mount(navbar, {
+ mixins: [mockMixin],
+ });
+ wrapper.vm.updateButtonText("newText");
+
+ // Assert
+ expect(wrapper.componentVM.customButtontext).toBe("newText");
+ });
+
+ test("should run removeLoader fn on buttonMain and return false for onkeydown fn", async () => {
+ // Arrange
+ const wrapper = mount(navbar, {
+ mixins: [mockMixin],
+ });
+
+ // Act
+ wrapper.vm.$refs.buttonMain.removeLoader = jest.fn();
+ wrapper.vm.removeLoader();
+ const spy = jest.spyOn(document, "onkeydown");
+ document.onkeydown();
+
+ // Assert
+ expect(wrapper.vm.$refs.buttonMain.removeLoader).toHaveBeenCalled();
+ expect(spy).toReturnWith(true);
+ });
+});
+
+const mockMixin = {
+ methods: {
+ getCmsContent: jest.fn(),
+ getFooterInfoBoxHeight: jest.fn(() => 80),
+ },
+};
diff --git a/src/iss-components/nav-bar/nav-bar.vue b/src/iss-components/nav-bar/nav-bar.vue
new file mode 100644
index 00000000..631e5c0e
--- /dev/null
+++ b/src/iss-components/nav-bar/nav-bar.vue
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
+
diff --git a/src/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button.spec.js b/src/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button.spec.js
new file mode 100644
index 00000000..8cf6c55b
--- /dev/null
+++ b/src/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button.spec.js
@@ -0,0 +1,104 @@
+import { shallowMount } from "@vue/test-utils";
+import { getMountOptions } from "@/helpers/unit-test-helper.js";
+
+import paymentMethodListButton from "@/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button";
+
+const testConstants = {
+ images: {
+ A: "imageA",
+ B: "imageB",
+ NONE: null,
+ },
+ names: {
+ A: "nameA",
+ B: "nameB",
+ },
+ content: {
+ withInline: "Button text with {custom:inlineImage} inline.",
+ noInline: "Button text with no inline",
+ },
+};
+
+let cmsContent;
+
+describe("Payment Method Question", () => {
+ beforeEach(() => {
+ cmsContent = {};
+ });
+
+ describe("Side image", () => {
+ it("Renders side image if image is present and not inline", () => {
+ // Arrange
+ const props = generateDefaultProps();
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ const showSideImage = wrapper.vm.shouldDisplaySideImage;
+
+ expect(showSideImage).toBe(true);
+ });
+
+ it("Does not render side image if no image is present", () => {
+ // Arrange
+ let props = generateDefaultProps();
+
+ props.buttonImage = testConstants.images.NONE;
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ const showSideImage = wrapper.vm.shouldDisplaySideImage;
+
+ expect(showSideImage).toBe(false);
+ });
+
+ it("Does not render side image if inline", () => {
+ // Arrange
+ let props = generateDefaultProps();
+
+ props.buttonLabel = testConstants.content.withInline;
+ props.altText = testConstants.content.withInline;
+
+ const { wrapper } = setupMocks({
+ propsData: props,
+ });
+
+ // Act
+ const showSideImage = wrapper.vm.shouldDisplaySideImage;
+
+ expect(showSideImage).toBe(false);
+ });
+ });
+});
+
+function generateDefaultProps() {
+ return {
+ buttonLabel: testConstants.noInline,
+ altText: testConstants.noInline,
+ groupName: "payment-method",
+ value: testConstants.names.A,
+ buttonImage: testConstants.images.A,
+ };
+}
+
+function setupMocks(customMountOptions) {
+ const mountOptions = getMountOptions(customMountOptions);
+
+ const mockMixin = {
+ methods: {
+ getCmsContent: jest.fn((widgetName, cmsFieldName) => {
+ return cmsContent?.[widgetName]?.[cmsFieldName] ?? "";
+ }),
+ },
+ };
+
+ mountOptions.global.mixins = [mockMixin];
+
+ const wrapper = shallowMount(paymentMethodListButton, mountOptions);
+ wrapper.vm.setCmsContent = jest.fn();
+ return { wrapper };
+}
diff --git a/src/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button.vue b/src/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button.vue
new file mode 100644
index 00000000..2763f1af
--- /dev/null
+++ b/src/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button.vue
@@ -0,0 +1,123 @@
+
+