Skip to content

Commit

Permalink
Add unit tests for sharing data store (#34206)
Browse files Browse the repository at this point in the history
* Enhance RecordBarMeter component with `className`

* Add changelog

* Add store types

* Update store selectors and actions

* Update consumer hook to use new selectors

* Create useShareLimits hook

* Move `ShareCounter` to publicize-components and name it `ShareLimitsBar`

* Create separate notice components

* Fix the post editor notices

* Update Jetpack Social admin page to use the new meter bar

* Remove unused code left after #34111

* Add changelog

* Fix share count

* Update index.js

* Include active connections count for notices

* Fix i18n build error

* Enhance RecordBarMeter component with `className`

* Add changelog

* Extract constants and improve types

* Add types/jest

* Add tests for sharesData selectors

* Add tests for useShareLimits hook

* rename to *.test.js

* extract utility

* Create add-tests-for-sharing-data

* Update shares-data.test.js

* Extract messages to utility function

* Use the messages from utility function

* Enhance RecordBarMeter component with `className`

* Add changelog

* Fix up versions

* Revert "Remove unused code left after #34111"

This reverts commit ca45999.

* Use @wordpress/element instead of react

* Fix messaging

* Let TS infer type

* Combine the share limits logic into a single useSelect call

* Fix the limits shown even after a paid plan

* Enhance RecordBarMeter component with `className`

* Add changelog

* Enhance RecordBarMeter component with `className`

* Add changelog

* Jetpack Social | Warn the user that their scheduled posts won't get shared if they will get over limits. (#34183)

* Enhance RecordBarMeter component with `className`

* Add changelog

* Add store types

* Update store selectors and actions

* Update consumer hook to use new selectors

* Create useShareLimits hook

* Move `ShareCounter` to publicize-components and name it `ShareLimitsBar`

* Create separate notice components

* Fix the post editor notices

* Update Jetpack Social admin page to use the new meter bar

* Remove unused code left after #34111

* Add changelog

* Fix share count

* Update index.js

* Include active connections count for notices

* Fix i18n build error

* Enhance RecordBarMeter component with `className`

* Add changelog

* Extract constants and improve types

* Extract messages to utility function

* Enhance RecordBarMeter component with `className`

* Add changelog

* Fix up versions

* Revert "Remove unused code left after #34111"

This reverts commit ca45999.

* Use @wordpress/element instead of react

* Fix messaging

* Let TS infer type

* Combine the share limits logic into a single useSelect call

* Fix the limits shown even after a paid plan

* Update tests
  • Loading branch information
manzoorwanijk committed Dec 12, 2023
1 parent 4bef795 commit 80ff9da
Show file tree
Hide file tree
Showing 6 changed files with 652 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: added


51 changes: 26 additions & 25 deletions projects/js-packages/publicize-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,21 @@
"@automattic/jetpack-connection": "workspace:*",
"@automattic/jetpack-shared-extension-utils": "workspace:*",
"@automattic/social-previews": "2.0.1-beta.10",
"@wordpress/annotations": "2.47.0",
"@wordpress/api-fetch": "6.44.0",
"@wordpress/block-editor": "12.15.0",
"@wordpress/blocks": "12.24.0",
"@wordpress/components": "25.13.0",
"@wordpress/compose": "6.24.0",
"@wordpress/data": "9.17.0",
"@wordpress/edit-post": "7.24.0",
"@wordpress/editor": "13.24.0",
"@wordpress/element": "5.24.0",
"@wordpress/hooks": "3.47.0",
"@wordpress/html-entities": "3.47.0",
"@wordpress/i18n": "4.47.0",
"@wordpress/icons": "9.38.0",
"@wordpress/notices": "4.15.0",
"@wordpress/annotations": "2.45.0",
"@wordpress/api-fetch": "6.42.0",
"@wordpress/block-editor": "12.13.0",
"@wordpress/blocks": "12.22.0",
"@wordpress/components": "25.11.0",
"@wordpress/compose": "6.22.0",
"@wordpress/data": "9.15.0",
"@wordpress/edit-post": "7.22.0",
"@wordpress/editor": "13.22.0",
"@wordpress/element": "5.22.0",
"@wordpress/hooks": "3.45.0",
"@wordpress/html-entities": "3.45.0",
"@wordpress/i18n": "4.45.0",
"@wordpress/icons": "9.36.0",
"@wordpress/notices": "4.13.0",
"classnames": "2.3.2",
"prop-types": "15.8.1",
"react-page-visibility": "7.0.0",
Expand All @@ -47,19 +47,20 @@
"@automattic/color-studio": "2.5.0",
"@automattic/jetpack-base-styles": "workspace:*",
"@automattic/jetpack-webpack-config": "workspace:*",
"@babel/core": "7.23.5",
"@babel/plugin-transform-react-jsx": "7.23.4",
"@babel/preset-react": "7.23.3",
"@babel/runtime": "7.23.5",
"@testing-library/dom": "8.20.1",
"@babel/core": "7.23.2",
"@babel/plugin-transform-react-jsx": "7.22.15",
"@babel/preset-react": "7.22.15",
"@babel/runtime": "7.23.2",
"@testing-library/dom": "8.19.1",
"@testing-library/react": "13.4.0",
"@testing-library/user-event": "14.5.1",
"@testing-library/user-event": "14.4.3",
"@types/jest": "29.2.5",
"@types/react": "18.2.33",
"@wordpress/babel-plugin-import-jsx-pragma": "4.30.0",
"@wordpress/core-data": "6.24.0",
"@wordpress/babel-plugin-import-jsx-pragma": "4.28.0",
"@wordpress/core-data": "6.22.0",
"babel-jest": "29.4.3",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"jest": "29.4.3",
"jest-environment-jsdom": "29.4.3",
"react": "18.2.0",
"react-dom": "18.2.0"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
import { renderHook } from '@testing-library/react';
import { RegistryProvider, createRegistry, createReduxStore } from '@wordpress/data';
import { WPDataRegistry } from '@wordpress/data/build-types/registry';
import { getMessages, useShareLimits } from '../';
import { SOCIAL_STORE_CONFIG, SOCIAL_STORE_ID } from '../../../social-store';
import { SocialStoreState } from '../../../social-store/types';
import { createActiveConnections } from '../../../utils/test-utils';

type DeepPartial< T > = T extends object
? {
[ P in keyof T ]?: DeepPartial< T[ P ] >;
}
: T;

/**
* Create a registry with stores.
*
* @param {Partial< SocialStoreState >} initialState - Initial state for the store.
*
* @returns {WPDataRegistry} Registry.
*/
function createRegistryWithStores( initialState = {} ) {
// Create a registry.
const registry = createRegistry();

const socialStore = createReduxStore( SOCIAL_STORE_ID, { ...SOCIAL_STORE_CONFIG, initialState } );
// Register stores.
// @ts-expect-error The registry type is not correct. This comment can be removed when register() exists in the type.
registry.register( socialStore );

return registry;
}

/**
* Returns the initial state for the store.
*
* @param {Partial< SocialStoreState >} data - Data to override the default state
*
* @returns {SocialStoreState} Initial state for the store
*/
function getStoreInitialState( data: DeepPartial< SocialStoreState > ) {
return {
...data,
sharesData: {
is_share_limit_enabled: true,
to_be_publicized_count: 0,
share_limit: 30,
publicized_count: 0,
show_advanced_plan_upgrade_nudge: false,
shared_posts_count: 0,
...data.sharesData,
},
};
}

const messages = getMessages( 30 );

describe( 'useShareLimits', () => {
it( 'should return the default values', () => {
const { result } = renderHook( () => useShareLimits() );

expect( result.current ).toEqual( {
status: 'none',
noticeType: 'default',
message: messages.default,
} );
} );

const testCases = [
{
name: 'should return the default values at the beginning',
sharesData: {
publicized_count: 0,
to_be_publicized_count: 0,
},
expected: {
status: 'none',
noticeType: 'default',
message: messages.default,
},
},
{
name: 'should return "none" with default messages when used + scheduled < limit',
sharesData: {
publicized_count: 5,
to_be_publicized_count: 5,
},
expected: {
status: 'none',
noticeType: 'default',
message: messages.default,
},
},
{
name: 'should return "full" with limit exceeded message when the limit is reached without scheduled posts',
sharesData: {
publicized_count: 30,
to_be_publicized_count: 0,
},
expected: {
status: 'full',
noticeType: 'error',
message: messages.exceeded,
},
},
{
name: 'should return "full" with scheduled shares message when the limit is reached with scheduled posts',
sharesData: {
publicized_count: 15,
to_be_publicized_count: 15,
},
expected: {
status: 'full',
noticeType: 'warning',
message: messages.scheduled,
},
},
{
name: 'should return "crossed" with limit exceeded message when the limit is crossed without scheduled posts',
sharesData: {
publicized_count: 35, // impossible to reach this number but just in case
to_be_publicized_count: 0,
},
expected: {
status: 'exceeded',
noticeType: 'error',
message: messages.exceeded,
},
},
{
name: 'should return "crossed" with limit exceeded message when the limit is crossed with scheduled posts',
sharesData: {
publicized_count: 30,
to_be_publicized_count: 5,
},
expected: {
status: 'exceeded',
noticeType: 'error',
message: messages.exceeded,
},
},
{
name: 'should return "approaching" with approaching limit message when the limit is approached without scheduled posts',
sharesData: {
publicized_count: 25,
to_be_publicized_count: 0,
},
expected: {
status: 'approaching',
noticeType: 'warning',
message: messages.approaching,
},
},
{
name: 'should return "approaching" with approaching limit message when the limit is approached with scheduled posts',
sharesData: {
publicized_count: 20,
to_be_publicized_count: 5,
},
expected: {
status: 'approaching',
noticeType: 'warning',
message: messages.approaching,
},
},
{
name: 'should return "none" when everything including active connections is well below the limit',
sharesData: {
publicized_count: 5,
to_be_publicized_count: 5,
},
connectionData: {
connections: createActiveConnections( 5 ),
},
expected: {
status: 'none',
noticeType: 'default',
message: messages.default,
},
},
{
name: 'should return "approaching" when approaching the limit with active connections',
sharesData: {
publicized_count: 10,
to_be_publicized_count: 10,
},
connectionData: {
connections: createActiveConnections( 5 ),
},
expected: {
status: 'approaching',
noticeType: 'warning',
message: messages.approaching,
},
},
{
name: 'should return "full" with a warning when the limit is reached with active connections',
sharesData: {
publicized_count: 15,
to_be_publicized_count: 10,
},
connectionData: {
connections: createActiveConnections( 5 ),
},
expected: {
status: 'full',
noticeType: 'warning',
message: messages.scheduled,
},
},
{
name: 'should return "crossed" with a warning when the limit is crossed with active connections',
sharesData: {
publicized_count: 20,
to_be_publicized_count: 10,
},
connectionData: {
connections: createActiveConnections( 5 ),
},
expected: {
status: 'exceeded',
noticeType: 'warning',
message: messages.scheduled,
},
},
];

for ( const { name, expected, ...initiaState } of testCases ) {
describe( 'dynamic tests', () => {
it( `${ name }`, () => {
const { result } = renderHook( () => useShareLimits(), {
wrapper: ( { children } ) => (
<RegistryProvider
value={ createRegistryWithStores( getStoreInitialState( initiaState ) ) }
>
{ children }
</RegistryProvider>
),
} );

expect( result.current ).toEqual( expected );
} );
} );
}
} );
Loading

0 comments on commit 80ff9da

Please sign in to comment.