Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FarhanNurzi/P2PS-1329/Advertisers ads are duplicating in other advertiser profile after manual refresh #9569

Merged
1 change: 1 addition & 0 deletions packages/p2p/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ module.exports = {
'<rootDir>/coverage/lcov-report',
'<rootDir>/dist',
],
transformIgnorePatterns: ['/node_modules/(?!@sendbird/chat).+\\.js$'],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To fix @sendbird/chat error when running jest

};
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import { render } from '@testing-library/react';
import { useModalManagerContext } from 'Components/modal-manager/modal-manager-context';
import { useStores } from 'Stores/index';
import AdvertiserPage from '../advertiser-page';

const mock_modal_manager = {
showModal: jest.fn(),
hideModal: jest.fn(),
useRegisterModalProps: jest.fn(),
is_modal_open: true,
};

jest.mock('Components/modal-manager/modal-manager-context');
const mocked_useModalManagerContext = useModalManagerContext as jest.MockedFunction<
() => Partial<ReturnType<typeof useModalManagerContext>>
>;

mocked_useModalManagerContext.mockImplementation(() => mock_modal_manager);

const mock_store: DeepPartial<ReturnType<typeof useStores>> = {
advertiser_page_store: {
advertiser_details_id: 'id1',
advertiser_details_name: 'test name',
counterparty_advertiser_info: {
name: 'name',
is_online: 1,
},
is_counterparty_advertiser_blocked: false,
onAdvertiserIdUpdate: jest.fn(),
onMount: jest.fn(),
onTabChange: jest.fn(),
setIsDropdownMenuVisible: jest.fn(),
onUnmount: jest.fn(),
onCancel: jest.fn(),
is_loading: false,
info: {
name: 'name',
},
},
general_store: {
advertiser_id: 'id2',
advertiser_info: {
name: 'my name',
is_online: 1,
},
block_unblock_user_error: '',
error_code: '',
active_index: 0,
setBlockUnblockUserError: jest.fn(),
setActiveIndex: jest.fn(),
path: {
my_profile: 3,
},
is_block_unblock_user_loading: false,
setCounterpartyAdvertiserId: jest.fn(),
},
buy_sell_store: {
show_advertiser_page: true,
hideAdvertiserPage: jest.fn(),
},
my_profile_store: {
setActiveTab: jest.fn(),
},
};

jest.mock('Components/advertiser-page/advertiser-page-adverts', () => jest.fn(() => <div>adverts</div>));
jest.mock('Components/advertiser-page/advertiser-page-stats', () => jest.fn(() => <div>stats</div>));
jest.mock('@deriv/components', () => ({
...jest.requireActual('@deriv/components'),
Loading: jest.fn(() => <div> loading...</div>),
}));

jest.mock('Stores', () => ({
...jest.requireActual('Stores'),
useStores: jest.fn(() => mock_store),
}));

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: jest.fn(() => ({
hash: '',
key: '0',
pathname: '/cashier/p2p/advertiser',
search: '?id=39',
})),
}));

describe('<Advertiserpage />', () => {
it('should call setCounterpartyAdvertiserId when component mounted', () => {
render(<AdvertiserPage />);
expect(mock_store.general_store.setCounterpartyAdvertiserId).toHaveBeenCalled();
});
});
26 changes: 17 additions & 9 deletions packages/p2p/src/components/advertiser-page/advertiser-page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DesktopWrapper, Loading, MobileWrapper, Text } from '@deriv/components'
import { daysSince, isMobile } from '@deriv/shared';
import { reaction } from 'mobx';
import { observer } from 'mobx-react-lite';
import { useHistory } from 'react-router-dom';
import { useHistory, useLocation } from 'react-router-dom';
import { useStores } from 'Stores';
import { Localize, localize } from 'Components/i18next';
import { my_profile_tabs } from 'Constants/my-profile-tabs';
Expand All @@ -25,12 +25,15 @@ import './advertiser-page.scss';
const AdvertiserPage = () => {
const { advertiser_page_store, buy_sell_store, general_store, my_profile_store } = useStores();
const { hideModal, showModal, useRegisterModalProps } = useModalManagerContext();
const { advertiser_details_name, advertiser_details_id, counterparty_advertiser_info } = advertiser_page_store;
const { advertiser_id, advertiser_info, counterparty_advertiser_id } = general_store;

const is_my_advert = advertiser_page_store.advertiser_details_id === general_store.advertiser_id;
const is_my_advert = advertiser_details_id === advertiser_id;
// Use general_store.advertiser_info since resubscribing to the same id from advertiser page returns error
const info = is_my_advert ? general_store.advertiser_info : advertiser_page_store.counterparty_advertiser_info;
const info = is_my_advert ? advertiser_info : counterparty_advertiser_info;

const history = useHistory();
const location = useLocation();

const {
basic_verification,
Expand All @@ -49,11 +52,11 @@ const AdvertiserPage = () => {
sell_orders_count,
} = info;

const nickname = advertiser_page_store.advertiser_details_name ?? name;

const joined_since = daysSince(created_time);
const nickname = advertiser_details_name ?? name;
// rating_average_decimal converts rating_average to 1 d.p number
const rating_average_decimal = rating_average ? Number(rating_average).toFixed(1) : null;
const joined_since = daysSince(created_time);

const error_message = () => {
return !!advertiser_page_store.is_counterparty_advertiser_blocked && !is_my_advert
? localize("Unblocking wasn't possible as {{name}} is not using Deriv P2P anymore.", {
Expand All @@ -65,6 +68,11 @@ const AdvertiserPage = () => {
};

React.useEffect(() => {
if (location.search || counterparty_advertiser_id) {
const url_params = new URLSearchParams(location.search);
general_store.setCounterpartyAdvertiserId(url_params.get('id'));
}

advertiser_page_store.onMount();
advertiser_page_store.setIsDropdownMenuVisible(false);

Expand All @@ -77,11 +85,11 @@ const AdvertiserPage = () => {
{ fireImmediately: true }
);

reaction(
const disposeBlockUnblockUserErrorReaction = reaction(
() => [advertiser_page_store.active_index, general_store.block_unblock_user_error],
() => {
advertiser_page_store.onTabChange();
if (general_store.block_unblock_user_error && buy_sell_store.show_advertiser_page) {
if (general_store.block_unblock_user_error) {
showModal({
key: 'ErrorModal',
props: {
Expand Down Expand Up @@ -109,14 +117,14 @@ const AdvertiserPage = () => {
width: isMobile() ? '90rem' : '40rem',
},
});
general_store.setBlockUnblockUserError(null);
}
},
{ fireImmediately: true }
);

return () => {
disposeCounterpartyAdvertiserIdReaction();
disposeBlockUnblockUserErrorReaction();
advertiser_page_store.onUnmount();
};

Expand Down
1 change: 0 additions & 1 deletion packages/p2p/src/components/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ const App = () => {
} else if (/\/advertiser$/.test(location.pathname)) {
if (location.search || general_store.counterparty_advertiser_id) {
const url_params = new URLSearchParams(location.search);
general_store.setCounterpartyAdvertiserId(url_params.get('id'));

// DO NOT REMOVE. This will prevent the page from redirecting to buy sell on reload from advertiser page
// as it resets the URL search params
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import { render } from '@testing-library/react';
import { useStores } from 'Stores/index';
import PaymentMethods from '../payment-methods';

let mock_store: DeepPartial<ReturnType<typeof useStores>>;

jest.mock('Stores', () => ({
...jest.requireActual('Stores'),
useStores: jest.fn(() => mock_store),
}));

jest.mock('Components/my-profile/payment-methods/add-payment-method', () => jest.fn(() => <div>AddPaymentMethod</div>));
jest.mock('Components/my-profile/payment-methods/payment-methods-list/edit-payment-method-form', () =>
jest.fn(() => <div>EditPaymentMethodForm</div>)
);
jest.mock('Components/my-profile/payment-methods/payment-methods-empty', () =>
jest.fn(() => <div>PaymentMethodsEmpty</div>)
);
jest.mock('Components/my-profile/payment-methods/payment-methods-list', () =>
jest.fn(() => <div>PaymentMethodsList</div>)
);

describe('<PaymentMethods />', () => {
beforeEach(() => {
mock_store = {
general_store: {
active_index: 3,
setFormikRef: jest.fn(),
},
my_profile_store: {
advertiser_has_payment_methods: true,
hideAddPaymentMethodForm: jest.fn(),
is_loading: false,
getAdvertiserPaymentMethods: jest.fn(),
getPaymentMethodsList: jest.fn(),
setAddPaymentMethodErrorMessage: jest.fn(),
setIsLoading: jest.fn(),
setShouldShowAddPaymentMethodForm: jest.fn(),
setShouldShowEditPaymentMethodForm: jest.fn(),
should_show_add_payment_method_form: false,
},
};
});

it('should call getPaymentMethodsList when component mounted', () => {
render(<PaymentMethods />);
expect(mock_store.my_profile_store.getPaymentMethodsList).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const PaymentMethods = ({ formik_ref }) => {
React.useEffect(() => {
my_profile_store.setIsLoading(true);
my_profile_store.getAdvertiserPaymentMethods();
my_profile_store.getPaymentMethodsList();
my_profile_store.setShouldShowAddPaymentMethodForm(false);
my_profile_store.setShouldShowEditPaymentMethodForm(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
14 changes: 6 additions & 8 deletions packages/p2p/src/stores/advertiser-page-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ export default class AdvertiserPageStore extends BaseStore {
? { local_currency: buy_sell_store.selected_local_currency }
: {}),
}).then(response => {
if (response.error) {
if (response?.error) {
this.setErrorMessage(response.error);
} else {
const { list } = response.p2p_advert_list;
const { list } = response?.p2p_advert_list;

this.setAdverts(list);
this.setHasMoreAdvertsToLoad(list.length >= general_store.list_item_limit);
Expand Down Expand Up @@ -212,7 +212,7 @@ export default class AdvertiserPageStore extends BaseStore {
p2p_advertiser_info: 1,
id: general_store.counterparty_advertiser_id,
}).then(response => {
if (response.error) {
if (response?.error) {
this.setErrorMessage(response.error);
} else {
this.setAdvertiserInfo(response);
Expand All @@ -224,11 +224,9 @@ export default class AdvertiserPageStore extends BaseStore {
}

onSubmit() {
this.root_store.general_store.blockUnblockUser(
!this.is_counterparty_advertiser_blocked,
this.advertiser_details_id
);
if (this.is_counterparty_advertiser_blocked) this.getCounterpartyAdvertiserList(this.advertiser_details_id);
const current_advertiser_id = this.advertiser_details_id ?? this.counterparty_advertiser_info?.id;
this.root_store.general_store.blockUnblockUser(!this.is_counterparty_advertiser_blocked, current_advertiser_id);
if (this.is_counterparty_advertiser_blocked) this.getCounterpartyAdvertiserList(current_advertiser_id);
this.setIsDropdownMenuVisible(false);
}

Expand Down
1 change: 1 addition & 0 deletions packages/p2p/src/stores/general-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export default class GeneralStore extends BaseStore {
);
}
} else {
this.hideModal();
const { code, message } = response.error;
this.setErrorCode(code);
this.setBlockUnblockUserError(message);
Expand Down
6 changes: 3 additions & 3 deletions packages/p2p/src/stores/my-profile-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ export default class MyProfileStore extends BaseStore {
requestWS({
p2p_advertiser_payment_methods: 1,
}).then(response => {
if (response.error) {
if (response?.error) {
this.setAdvertiserPaymentMethodsError(response.error.message);
} else {
this.setAdvertiserPaymentMethods(response?.p2p_advertiser_payment_methods);
Expand Down Expand Up @@ -562,7 +562,7 @@ export default class MyProfileStore extends BaseStore {
p2p_advertiser_update: 1,
show_name: this.root_store?.general_store?.should_show_real_name ? 1 : 0,
}).then(response => {
if (response.error) {
if (response?.error) {
this.setFormError(response.error.message);
this.root_store.general_store.setShouldShowRealName(
!this.root_store?.general_store?.should_show_real_name
Expand Down Expand Up @@ -661,7 +661,7 @@ export default class MyProfileStore extends BaseStore {
},
},
}).then(response => {
if (response.error) {
if (response?.error) {
this.setAddPaymentMethodErrorMessage(response.error.message);
this.root_store.general_store.showModal({
key: 'AddPaymentMethodErrorModal',
Expand Down