diff --git a/app/panel/components/Tooltip.jsx b/app/panel/components/Tooltip.jsx
index 1cf8a204a..bb28f6128 100644
--- a/app/panel/components/Tooltip.jsx
+++ b/app/panel/components/Tooltip.jsx
@@ -13,6 +13,7 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
+import ClassNames from 'classnames';
/**
* @class Implements a Tooltip component that is used in many panel views.
@@ -52,12 +53,14 @@ class Tooltip extends React.Component {
}
/**
- * Implements mouseenter. Sets a 1 second delay for showing the tooltip.
+ * Implements mouseenter. Sets a delay for showing the tooltip with a default of 1 second.
*/
delayHover() {
+ const delayType = typeof this.props.delay;
+ const delay = (delayType === 'number' || delayType === 'string') ? +this.props.delay : 1000;
this.delay = setTimeout(() => {
this.enter();
- }, 1000);
+ }, delay);
}
/**
@@ -83,8 +86,12 @@ class Tooltip extends React.Component {
* @return {JSX} JSX for rendering the Tooltip component
*/
render() {
+ const compClassNames = ClassNames({
+ 'dark-theme': this.props.theme === 'dark',
+ });
+
return (
-
+
{this.state.show &&
{this.props.header &&
diff --git a/app/panel/components/__tests__/RewardDetail.jsx b/app/panel/components/__tests__/RewardDetail.jsx
new file mode 100644
index 000000000..ccbd45a48
--- /dev/null
+++ b/app/panel/components/__tests__/RewardDetail.jsx
@@ -0,0 +1,179 @@
+/**
+ * Reward Detail Test Component
+ *
+ * Ghostery Browser Extension
+ * https://www.ghostery.com/
+ *
+ * Copyright 2018 Ghostery, Inc. All rights reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0
+ */
+
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { shallow } from 'enzyme';
+import RewardDetail from '../BuildingBlocks/RewardDetail';
+
+// Fake the translation function to only return the translation key
+global.t = function (str) {
+ return str;
+};
+
+// Fake the Tooltip implementation
+jest.mock('../Tooltip');
+
+describe('app/panel/components/BuildingBlocks/RewardDetail.jsx', () => {
+ describe('Snapshot tests with react-test-renderer', () => {
+ test('reward detail is rendered with all values present', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ code: 'test_code',
+ conditions: 'test reward conditions',
+ description: 'test reward description',
+ expires: 1527880170315,
+ id: 'test_reward_id',
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ pictureUrl: 'https://www.ghostery.com/wp-content/uploads/2017/12/simple-detailed-1024x833.png',
+ redeemUrl: 'https://www.offer-redeem-test.com',
+ redeemText: 'redeem now',
+ text: 'test reward title'
+ };
+ const component = renderer.create().toJSON();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('reward detail is rendered with missing text', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ code: 'test_code',
+ conditions: 'test reward conditions',
+ description: 'test reward description',
+ expires: 1527880170315,
+ id: 'test_reward_id',
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ pictureUrl: 'https://www.ghostery.com/wp-content/uploads/2017/12/simple-detailed-1024x833.png',
+ redeemUrl: 'https://www.offer-redeem-test.com',
+ redeemText: 'redeem now',
+ text: ''
+ };
+ const component = renderer.create().toJSON();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('reward detail is rendered with missing description', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ code: 'test_code',
+ conditions: 'test reward conditions',
+ description: '',
+ expires: 1527880170315,
+ id: 'test_reward_id',
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ pictureUrl: 'https://www.ghostery.com/wp-content/uploads/2017/12/simple-detailed-1024x833.png',
+ redeemUrl: 'https://www.offer-redeem-test.com',
+ redeemText: 'redeem now',
+ text: 'test reward title'
+ };
+ const component = renderer.create().toJSON();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('reward detail is rendered with missing code', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ code: '',
+ conditions: 'test reward conditions',
+ description: 'test reward description',
+ expires: 1527880170315,
+ id: 'test_reward_id',
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ pictureUrl: 'https://www.ghostery.com/wp-content/uploads/2017/12/simple-detailed-1024x833.png',
+ redeemUrl: 'https://www.offer-redeem-test.com',
+ redeemText: 'redeem now',
+ text: 'test reward title'
+ };
+ const component = renderer.create().toJSON();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('reward detail is rendered with missing conditions', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ code: 'test_code',
+ conditions: '',
+ description: 'test reward description',
+ expires: 1527880170315,
+ id: 'test_reward_id',
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ pictureUrl: 'https://www.ghostery.com/wp-content/uploads/2017/12/simple-detailed-1024x833.png',
+ redeemUrl: 'https://www.offer-redeem-test.com',
+ redeemText: 'redeem now',
+ text: 'test reward title'
+ };
+ const component = renderer.create().toJSON();
+ expect(component).toMatchSnapshot();
+ });
+ });
+
+ describe('Shallow snapshot tests rendered with Enzyme', () => {
+ test('reward detail is rendered correctly the code is copied', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ code: 'test_code',
+ conditions: 'test reward conditions',
+ description: 'test reward description',
+ expires: 1527880170315,
+ id: 'test_reward_id',
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ pictureUrl: 'https://www.ghostery.com/wp-content/uploads/2017/12/simple-detailed-1024x833.png',
+ redeemUrl: 'https://www.offer-redeem-test.com',
+ redeemText: 'redeem now',
+ text: 'test reward title'
+ };
+ const component = shallow();
+ expect(component.text()).toEqual(expect.stringContaining('rewards_copy_code'));
+ expect(component.text()).not.toEqual(expect.stringContaining('rewards_code_copied'));
+ component.setState({ copyText: t('rewards_code_copied') });
+ expect(component.text()).not.toEqual(expect.stringContaining('rewards_copy_code'));
+ expect(component.text()).toEqual(expect.stringContaining('rewards_code_copied'));
+ });
+ });
+});
diff --git a/app/panel/components/__tests__/RewardListItem.jsx b/app/panel/components/__tests__/RewardListItem.jsx
new file mode 100644
index 000000000..ec8e6440e
--- /dev/null
+++ b/app/panel/components/__tests__/RewardListItem.jsx
@@ -0,0 +1,156 @@
+/**
+ * Reward List Item Test Component
+ *
+ * Ghostery Browser Extension
+ * https://www.ghostery.com/
+ *
+ * Copyright 2018 Ghostery, Inc. All rights reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0
+ */
+
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { MemoryRouter } from 'react-router';
+import RewardListItem from '../BuildingBlocks/RewardListItem';
+
+// Fake the translation function to only return the translation key
+global.t = function (str) {
+ return str;
+};
+
+describe('app/panel/components/BuildingBlocks/RewardListItem.jsx', () => {
+ describe('Snapshot tests with react-test-renderer', () => {
+ test('reward list item is rendered correctly', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ disabled: false,
+ expires: 1527885633645,
+ id: 'test_reward_id',
+ index: 0,
+ isLong: false,
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ text: 'test reward title',
+ unread: false
+ };
+ const component = renderer.create(
+
+
+
+ ).toJSON();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('reward list item is rendered correctly when disabled', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ disabled: true,
+ expires: 1527885633645,
+ id: 'test_reward_id',
+ index: 0,
+ isLong: false,
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ text: 'test reward title',
+ unread: false
+ };
+ const component = renderer.create(
+
+
+
+ ).toJSON();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('reward list item is rendered correctly when unread', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ disabled: false,
+ expires: 1527885633645,
+ id: 'test_reward_id',
+ index: 0,
+ isLong: false,
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ text: 'test reward title',
+ unread: true
+ };
+ const component = renderer.create(
+
+
+
+ ).toJSON();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('reward list item is rendered correctly when elongated', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ disabled: false,
+ expires: 1527885633645,
+ id: 'test_reward_id',
+ index: 0,
+ isLong: true,
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ text: 'test reward title',
+ unread: false
+ };
+ const component = renderer.create(
+
+
+
+ ).toJSON();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('reward list item is rendered correctly when disabled, unread, and elongated', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ toggleOffersEnabled: () => {},
+ removeOffer: () => {},
+ setOfferRead: () => {},
+ sendSignal: () => {}
+ },
+ disabled: true,
+ expires: 1527885633645,
+ id: 'test_reward_id',
+ index: 0,
+ isLong: true,
+ logoUrl: 'https://www.ghostery.com/wp-content/themes/ghostery/images/ghostery_logo.svg',
+ text: 'test reward title',
+ unread: true
+ };
+ const component = renderer.create(
+
+
+
+ ).toJSON();
+ expect(component).toMatchSnapshot();
+ });
+ });
+});
diff --git a/app/panel/components/__tests__/Rewards.jsx b/app/panel/components/__tests__/Rewards.jsx
new file mode 100644
index 000000000..8ceb2cf7a
--- /dev/null
+++ b/app/panel/components/__tests__/Rewards.jsx
@@ -0,0 +1,66 @@
+/**
+ * Rewards Test Component
+ *
+ * Ghostery Browser Extension
+ * https://www.ghostery.com/
+ *
+ * Copyright 2018 Ghostery, Inc. All rights reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0
+ */
+
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { MemoryRouter } from 'react-router';
+import Rewards from '../Rewards';
+
+// Fake the translation function to only return the translation key
+global.t = function (str) {
+ return str;
+};
+
+describe('app/panel/components/Rewards.jsx', () => {
+ describe('Snapshot tests with react-test-renderer', () => {
+ test('rewards is rendered correctly when rewards is on and rewards is null', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ sendSignal: () => {},
+ },
+ location: {
+ pathname: '/detail/rewards/list',
+ },
+ enable_offers: true,
+ is_expanded: false
+ };
+ const component = renderer.create(
+
+
+
+ ).toJSON();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('rewards is rendered correctly when rewards is off and rewards is null', () => {
+ const initialState = {
+ actions: {
+ getRewardsData: () => {},
+ sendSignal: () => {},
+ },
+ location: {
+ pathname: '/detail/rewards/list',
+ },
+ enable_offers: false,
+ is_expanded: false
+ };
+ const component = renderer.create(
+
+
+
+ ).toJSON();
+ expect(component).toMatchSnapshot();
+ });
+ });
+});
diff --git a/app/panel/components/__tests__/__snapshots__/RewardDetail.jsx.snap b/app/panel/components/__tests__/__snapshots__/RewardDetail.jsx.snap
new file mode 100644
index 000000000..a6eb32169
--- /dev/null
+++ b/app/panel/components/__tests__/__snapshots__/RewardDetail.jsx.snap
@@ -0,0 +1,339 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`app/panel/components/BuildingBlocks/RewardDetail.jsx Snapshot tests with react-test-renderer reward detail is rendered with all values present 1`] = `
+
+
+
+
+
+
+ test reward title
+
+
+ test reward description
+
+
+
+
+ test_code
+
+
+
+
+ rewards_copy_code
+
+
+
+
+ rewards_expires_in
+
+
+
+ rewards_terms_conditions
+
+
+
+
+ redeem now
+
+
+`;
+
+exports[`app/panel/components/BuildingBlocks/RewardDetail.jsx Snapshot tests with react-test-renderer reward detail is rendered with missing code 1`] = `
+
+
+
+
+
+
+ test reward title
+
+
+ test reward description
+
+
+
+
+ rewards_expires_in
+
+
+
+ rewards_terms_conditions
+
+
+
+
+ redeem now
+
+
+`;
+
+exports[`app/panel/components/BuildingBlocks/RewardDetail.jsx Snapshot tests with react-test-renderer reward detail is rendered with missing conditions 1`] = `
+
+
+
+
+
+
+ test reward title
+
+
+ test reward description
+
+
+
+
+ test_code
+
+
+
+
+ rewards_copy_code
+
+
+
+
+ rewards_expires_in
+
+
+
+
+ redeem now
+
+
+`;
+
+exports[`app/panel/components/BuildingBlocks/RewardDetail.jsx Snapshot tests with react-test-renderer reward detail is rendered with missing description 1`] = `
+
+
+
+
+
+
+ test reward title
+
+
+
+
+
+ test_code
+
+
+
+
+ rewards_copy_code
+
+
+
+
+ rewards_expires_in
+
+
+
+ rewards_terms_conditions
+
+
+
+
+ redeem now
+
+
+`;
+
+exports[`app/panel/components/BuildingBlocks/RewardDetail.jsx Snapshot tests with react-test-renderer reward detail is rendered with missing text 1`] = `
+
+
+
+
+
+
+
+ test reward description
+
+
+
+
+ test_code
+
+
+
+
+ rewards_copy_code
+
+
+
+
+ rewards_expires_in
+
+
+
+ rewards_terms_conditions
+
+
+
+
+ redeem now
+
+
+`;
diff --git a/app/panel/components/__tests__/__snapshots__/RewardListItem.jsx.snap b/app/panel/components/__tests__/__snapshots__/RewardListItem.jsx.snap
new file mode 100644
index 000000000..cb4237378
--- /dev/null
+++ b/app/panel/components/__tests__/__snapshots__/RewardListItem.jsx.snap
@@ -0,0 +1,331 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`app/panel/components/BuildingBlocks/RewardListItem.jsx Snapshot tests with react-test-renderer reward list item is rendered correctly 1`] = `
+
+
+
+`;
+
+exports[`app/panel/components/BuildingBlocks/RewardListItem.jsx Snapshot tests with react-test-renderer reward list item is rendered correctly when disabled, unread, and elongated 1`] = `
+
+
+
+`;
diff --git a/app/panel/components/__tests__/__snapshots__/Rewards.jsx.snap b/app/panel/components/__tests__/__snapshots__/Rewards.jsx.snap
new file mode 100644
index 000000000..88bdf5132
--- /dev/null
+++ b/app/panel/components/__tests__/__snapshots__/Rewards.jsx.snap
@@ -0,0 +1,133 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`app/panel/components/Rewards.jsx Snapshot tests with react-test-renderer rewards is rendered correctly when rewards is off and rewards is null 1`] = `
+
+`;
+
+exports[`app/panel/components/Rewards.jsx Snapshot tests with react-test-renderer rewards is rendered correctly when rewards is on and rewards is null 1`] = `
+