/
githubmirror
/
wp-calypso
Обзор
Документация
Войти
/
githubmirror
/
wp-calypso
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
trunk
client/state/posts/test/utils.js
804 строки
19 KB
Griffith Chen
Lodash: replace find(), findLast() and has() with native equivalents (#111993)
26 июн 2026, 05:33
Не верифицирован
26 июн 2026, 05:33
0e3385a
Код
Авторство
О чём код?
import deepFreeze from 'deep-freeze'; import { appendToPostEditsLog, normalizePostForDisplay, normalizePostForState, normalizePostForApi, getNormalizedPostsQuery, getSerializedPostsQuery, getDeserializedPostsQueryDetails, getSerializedPostsQueryWithoutPage, getTermIdsFromEdits, isTermsEqual, applyPostEdits, mergePostEdits, getEditURL, getFeaturedImageId, getUnappliedMetadataEdits, } from '../utils'; describe( 'utils', () => { describe( 'isTermsEqual', () => { test( 'should return true if term edits are the same as saved terms', () => { const isEqual = isTermsEqual( { post_tag: [ 'ribs', 'chicken' ], category: [ { ID: 777, name: 'amazing food', }, ], }, { post_tag: { ribs: { ID: 11, name: 'ribs', }, chicken: { ID: 12, name: 'chicken', }, }, category: { 'amazing-food': { ID: 777, name: 'amazing food', }, }, } ); expect( isEqual ).toBe( true ); } ); test( 'should return false if term edits are not the same as saved terms', () => { const isEqual = isTermsEqual( { post_tag: [ 'ribs' ], category: [ { ID: 777, name: 'amazing food', }, ], }, { post_tag: { ribs: { ID: 11, name: 'ribs', }, chicken: { ID: 12, name: 'chicken', }, }, category: { 'amazing-food': { ID: 777, name: 'amazing food', }, }, } ); expect( isEqual ).toBe( false ); } ); test( 'should return false savedTerms is missing a taxonomy', () => { const isEqual = isTermsEqual( { post_tag: [ 'ribs' ], }, {} ); expect( isEqual ).toBe( false ); } ); } ); describe( 'normalizePostForApi()', () => { test( 'should return null if post is falsey', () => { const normalizedPost = normalizePostForApi(); expect( normalizedPost ).toBeNull(); } ); test( 'should return a normalized post object', () => { const post = { ID: 841, site_ID: 2916284, global_ID: '3d097cb7c5473c169bba0eb8e3c6cb64', title: 'Ribs & Chicken', terms: { category: [ { ID: 777, name: 'recipes' } ], post_tag: [ 'super', 'yummy', 'stuff' ], }, }; const normalizedPost = normalizePostForApi( post ); expect( normalizedPost ).toEqual( { ID: 841, site_ID: 2916284, global_ID: '3d097cb7c5473c169bba0eb8e3c6cb64', title: 'Ribs & Chicken', terms: { post_tag: [ 'super', 'yummy', 'stuff' ], }, } ); } ); } ); describe( 'normalizePostForDisplay()', () => { test( 'should return null if post is falsey', () => { const normalizedPost = normalizePostForDisplay(); expect( normalizedPost ).toBeNull(); } ); test( 'should return a normalized post object', () => { const post = { ID: 841, site_ID: 2916284, global_ID: '3d097cb7c5473c169bba0eb8e3c6cb64', title: 'Ribs & Chicken', author: { name: 'Badman <img onerror= />', }, post_thumbnail: { URL: 'https://example.com/logo.png', width: 700, height: 200, }, }; const normalizedPost = normalizePostForDisplay( post ); expect( normalizedPost ).toEqual( { ...post, title: 'Ribs & Chicken', author: { name: 'Badman ', }, canonical_image: { uri: 'https://example.com/logo.png', width: 700, height: 200, }, } ); } ); } ); describe( 'normalizePostForState()', () => { test( 'should deeply unset all meta links', () => { const original = deepFreeze( { ID: 814, meta: { links: {}, data: { autosave: true }, }, terms: { category: { meta: { ID: 171, name: 'meta', meta: { links: {}, }, }, }, post_tag: { meta: { ID: 171, name: 'meta', meta: { links: {}, }, }, }, }, categories: { meta: { ID: 171, name: 'meta', meta: { links: {}, }, }, }, tags: { meta: { ID: 171, name: 'meta', meta: { links: {}, }, }, }, attachments: { 14209: { ID: 14209, meta: { links: {}, }, }, }, } ); const revised = normalizePostForState( original ); expect( revised ).not.toEqual( original ); expect( revised ).toEqual( { ID: 814, meta: { data: { autosave: true }, }, terms: { category: { meta: { ID: 171, name: 'meta', meta: {}, }, }, post_tag: { meta: { ID: 171, name: 'meta', meta: {}, }, }, }, categories: { meta: { ID: 171, name: 'meta', meta: {}, }, }, tags: { meta: { ID: 171, name: 'meta', meta: {}, }, }, attachments: { 14209: { ID: 14209, meta: {}, }, }, } ); } ); } ); describe( '#getNormalizedPostsQuery()', () => { test( 'should exclude default values', () => { const query = getNormalizedPostsQuery( { page: 4, number: 20, } ); expect( query ).toEqual( { page: 4, } ); } ); } ); describe( '#getSerializedPostsQuery()', () => { test( 'should return a JSON string of a normalized query', () => { const serializedQuery = getSerializedPostsQuery( { type: 'page', page: 1, } ); expect( serializedQuery ).toBe( '{"type":"page"}' ); } ); test( 'should prefix site ID if specified', () => { const serializedQuery = getSerializedPostsQuery( { search: 'Hello', }, 2916284 ); expect( serializedQuery ).toBe( '2916284:{"search":"Hello"}' ); } ); } ); describe( 'getDeserializedPostsQueryDetails()', () => { test( 'should return undefined query and site if string does not contain JSON', () => { const queryDetails = getDeserializedPostsQueryDetails( 'bad' ); expect( queryDetails ).toEqual( { siteId: undefined, query: undefined, } ); } ); test( 'should return query but not site if string does not contain site prefix', () => { const queryDetails = getDeserializedPostsQueryDetails( '{"search":"hello"}' ); expect( queryDetails ).toEqual( { siteId: undefined, query: { search: 'hello' }, } ); } ); test( 'should return query and site if string contains site prefix and JSON', () => { const queryDetails = getDeserializedPostsQueryDetails( '2916284:{"search":"hello"}' ); expect( queryDetails ).toEqual( { siteId: 2916284, query: { search: 'hello' }, } ); } ); } ); describe( '#getSerializedPostsQueryWithoutPage()', () => { test( 'should return a JSON string of a normalized query omitting page', () => { const serializedQuery = getSerializedPostsQueryWithoutPage( { type: 'page', page: 2, } ); expect( serializedQuery ).toBe( '{"type":"page"}' ); } ); test( 'should prefix site ID if specified', () => { const serializedQuery = getSerializedPostsQueryWithoutPage( { search: 'Hello', page: 2, }, 2916284 ); expect( serializedQuery ).toBe( '2916284:{"search":"Hello"}' ); } ); } ); describe( 'appendToPostEditsLog', () => { test( 'should create a new log when input log is empty', () => { const newLog = appendToPostEditsLog( null, { title: 'Hello' } ); expect( newLog ).toEqual( [ { title: 'Hello' } ] ); } ); test( 'should append edit to an empty log', () => { const newLog = appendToPostEditsLog( [], { title: 'Hello' } ); expect( newLog ).toEqual( [ { title: 'Hello' } ] ); } ); test( 'should merge with last edit if it is not a save marker', () => { const newLog = appendToPostEditsLog( [ { title: 'Hello' } ], { content: 'World' } ); expect( newLog ).toEqual( [ { title: 'Hello', content: 'World' } ] ); } ); test( 'should append a new edit if the last one is a save marker', () => { const newLog = appendToPostEditsLog( [ { title: 'Hello' }, 'marker' ], { content: 'World' } ); expect( newLog ).toEqual( [ { title: 'Hello' }, 'marker', { content: 'World' } ] ); } ); } ); describe( 'mergePostEdits', () => { test( 'should return null when there are no objects to merge', () => { expect( mergePostEdits() ).toBeNull(); } ); test( 'should return null when there are no objects to merge, only markers', () => { expect( mergePostEdits( 'marker' ) ).toBeNull(); } ); test( 'should return identical object when called with only one object', () => { const postEdit = deepFreeze( { title: 'Hello' } ); const merged = mergePostEdits( postEdit ); expect( merged ).toBe( postEdit ); } ); test( 'should return identical object when called with only one object + markers', () => { const postEdit = deepFreeze( { title: 'Hello' } ); const merged = mergePostEdits( 'marker1', postEdit, 'marker2' ); expect( merged ).toBe( postEdit ); } ); test( 'should merge multiple objects', () => { const merged = mergePostEdits( deepFreeze( { title: 'Hello' } ), deepFreeze( { content: 'World' } ), deepFreeze( { excerpt: 'Hi' } ) ); expect( merged ).toEqual( { title: 'Hello', content: 'World', excerpt: 'Hi', } ); } ); test( 'should merge multiple objects with interlaced markers', () => { const merged = mergePostEdits( deepFreeze( { title: 'Hello' } ), 'marker1', deepFreeze( { content: 'World' } ), 'marker2', deepFreeze( { excerpt: 'Hi' } ) ); expect( merged ).toEqual( { title: 'Hello', content: 'World', excerpt: 'Hi', } ); } ); test( 'should merge into an empty object', () => { const merged = mergePostEdits( deepFreeze( {} ), { tags_by_id: [ 4, 5, 6 ], } ); expect( merged ).toEqual( { tags_by_id: [ 4, 5, 6 ], } ); } ); test( 'should not modify array properties in the original object', () => { const merged = mergePostEdits( deepFreeze( { tags_by_id: [ 4, 5, 6 ], } ), {} ); expect( merged ).toEqual( { tags_by_id: [ 4, 5, 6 ], } ); } ); test( 'should allow removing array items', () => { const merged = mergePostEdits( deepFreeze( { tags_by_id: [ 4, 5, 6 ], } ), { tags_by_id: [ 4, 6 ], } ); expect( merged ).toEqual( { tags_by_id: [ 4, 6 ], } ); } ); test( 'should replace arrays with the new value', () => { const merged = mergePostEdits( deepFreeze( { tags_by_id: [ 4, 5, 6 ], } ), { tags_by_id: [ 1, 2, 3, 4 ], } ); expect( merged ).toEqual( { tags_by_id: [ 1, 2, 3, 4 ], } ); } ); test( 'should add properties to nested objects', () => { const merged = mergePostEdits( deepFreeze( { discussion: { comments_open: false }, } ), { discussion: { pings_open: false }, } ); expect( merged ).toEqual( { discussion: { comments_open: false, pings_open: false }, } ); } ); test( 'should replace previous metadata edit', () => { const merged = mergePostEdits( deepFreeze( { metadata: [ { key: 'geo_latitude', operation: 'delete' } ], } ), { metadata: [ { key: 'geo_latitude', value: '20', operation: 'update' } ], } ); expect( merged ).toEqual( { metadata: [ { key: 'geo_latitude', value: '20', operation: 'update' } ], } ); } ); test( 'should add new metadata edit', () => { const merged = mergePostEdits( deepFreeze( { metadata: [ { key: 'geo_latitude', value: '10', operation: 'update' } ], } ), { metadata: [ { key: 'geo_longitude', value: '20', operation: 'update' } ], } ); expect( merged ).toEqual( { metadata: [ { key: 'geo_latitude', value: '10', operation: 'update' }, { key: 'geo_longitude', value: '20', operation: 'update' }, ], } ); } ); } ); describe( 'applyPostEdits', () => { test( 'should modify metadata', () => { const edited = applyPostEdits( deepFreeze( { metadata: [ { key: 'geo_latitude', value: '10' } ], } ), { metadata: [ { key: 'geo_latitude', value: '20', operation: 'update' } ], } ); expect( edited ).toEqual( { metadata: [ { key: 'geo_latitude', value: '20' } ], } ); } ); test( 'should add metadata', () => { const edited = applyPostEdits( deepFreeze( { metadata: [ { key: 'geo_latitude', value: '10' } ], } ), { metadata: [ { key: 'geo_longitude', value: '20', operation: 'update' } ], } ); expect( edited ).toEqual( { metadata: [ { key: 'geo_latitude', value: '10' }, { key: 'geo_longitude', value: '20' }, ], } ); } ); test( 'should remove metadata', () => { const edited = applyPostEdits( deepFreeze( { metadata: [ { key: 'geo_latitude', value: '10' }, { key: 'geo_longitude', value: '20' }, ], } ), { metadata: [ { key: 'geo_longitude', operation: 'delete' } ], } ); expect( edited ).toEqual( { metadata: [ { key: 'geo_latitude', value: '10' } ], } ); } ); test( 'should return unchanged object on noop update', () => { const post = deepFreeze( { metadata: [ { key: 'geo_latitude', value: '10' } ], } ); const edited = applyPostEdits( post, { metadata: [ { key: 'geo_latitude', value: '10', operation: 'update' } ], } ); expect( edited ).toEqual( post ); } ); test( 'should return unchanged object on noop delete', () => { const post = deepFreeze( { metadata: [ { key: 'geo_latitude', value: '10' } ], } ); const edited = applyPostEdits( post, { metadata: [ { key: 'geo_longitude', value: '10', operation: 'delete' } ], } ); expect( edited ).toEqual( post ); } ); test( 'should return metadata array after applying edits to a false value', () => { const post = deepFreeze( { metadata: false, // value returned by REST API for a new post } ); const edited = applyPostEdits( post, { metadata: [ { key: 'geo_latitude', value: '10', operation: 'update' } ], } ); expect( edited ).toEqual( { metadata: [ { key: 'geo_latitude', value: '10' } ], } ); } ); } ); describe( '#getTermIdsFromEdits()', () => { test( 'should return the same post edit object if no term edits have been made', () => { const normalizedPostEdits = getTermIdsFromEdits( { title: 'Chewbacca Saves', } ); expect( normalizedPostEdits ).toEqual( { title: 'Chewbacca Saves', } ); } ); test( 'should return the add terms_by_id if terms have been edited', () => { const originalPost = deepFreeze( { title: 'Chewbacca Saves', terms: { wookie_post_types: { awesomesauce: { ID: 777, name: 'Awesomesauce', }, }, }, } ); const normalizedPostEdits = getTermIdsFromEdits( originalPost ); expect( normalizedPostEdits ).toEqual( { title: 'Chewbacca Saves', terms: { wookie_post_types: { awesomesauce: { ID: 777, name: 'Awesomesauce', }, }, }, terms_by_id: { wookie_post_types: [ 777 ], }, } ); } ); test( 'should taxonomy terms_by_id to null if object is empty', () => { const normalizedPostEdits = getTermIdsFromEdits( { title: 'Chewbacca Saves', terms: { wookie_post_types: {}, }, } ); expect( normalizedPostEdits ).toEqual( { title: 'Chewbacca Saves', terms: { wookie_post_types: {}, }, terms_by_id: { wookie_post_types: null, }, } ); } ); test( 'should not set terms_by_id for taxonomies that set an array on terms', () => { const normalizedPostEdits = getTermIdsFromEdits( { title: 'Chewbacca Saves', terms: { wookie_post_tags: [ 'raaar', 'uggggaaarr' ], }, } ); expect( normalizedPostEdits ).toEqual( { title: 'Chewbacca Saves', terms: { wookie_post_tags: [ 'raaar', 'uggggaaarr' ], }, } ); } ); } ); describe( '#getEditURL', () => { test( 'should return correct path type=post is supplied', () => { const url = getEditURL( { ID: 123, type: 'post' }, { slug: 'en.blog.wordpress.com' } ); expect( url ).toEqual( '/post/en.blog.wordpress.com/123' ); } ); test( 'should return correct path type=page is supplied', () => { const url = getEditURL( { ID: 123, type: 'page' }, { slug: 'en.blog.wordpress.com' } ); expect( url ).toEqual( '/page/en.blog.wordpress.com/123' ); } ); test( 'should return correct path when custom post type is supplied', () => { const url = getEditURL( { ID: 123, type: 'jetpack-portfolio' }, { slug: 'en.blog.wordpress.com' } ); expect( url ).toEqual( '/edit/jetpack-portfolio/en.blog.wordpress.com/123' ); } ); test( 'should default to type=post if no post type is supplied', () => { const url = getEditURL( { ID: 123, type: '' }, { slug: 'en.blog.wordpress.com' } ); expect( url ).toEqual( '/post/en.blog.wordpress.com/123' ); } ); } ); describe( '#getFeaturedImageId()', () => { test( 'should return undefined when no post is specified', () => { expect( getFeaturedImageId() ).toBeUndefined(); } ); test( 'should return a non-URL featured_image property', () => { const id = getFeaturedImageId( { featured_image: 'media-1', post_thumbnail: { ID: 1, }, } ); expect( id ).toEqual( 'media-1' ); } ); test( 'should return a `null` featured_image property', () => { // This describes the behavior of unassigning a featured image // from the current post const id = getFeaturedImageId( { featured_image: null, post_thumbnail: { ID: 1, }, } ); expect( id ).toBeNull(); } ); test( 'should return empty string if that is the featured_image value', () => { // These values are typical for posts without a featured image const id = getFeaturedImageId( { featured_image: '', post_thumbnail: null, } ); expect( id ).toEqual( '' ); } ); test( 'should fall back to post thumbnail object ID if exists, if featured_image is URL', () => { const id = getFeaturedImageId( { featured_image: 'https://example.com/image.png', post_thumbnail: { ID: 1, }, } ); expect( id ).toEqual( 1 ); } ); test( "should return undefined if featured_image is URL and post thumbnail object doesn't exist", () => { const id = getFeaturedImageId( { featured_image: 'https://example.com/image.png', } ); expect( id ).toBeUndefined(); } ); } ); describe( '#getUnappliedMetadataEdits()', () => { const edits = [ { key: 'geo_latitude', value: '10', operation: 'update' }, { key: 'geo_longitude', operation: 'delete' }, ]; test( 'should treat false saved metadata as empty (REST shape for a new post)', () => { // The REST API returns `false` for a new post's metadata. expect( getUnappliedMetadataEdits( edits, false ) ).toEqual( [ { key: 'geo_latitude', value: '10', operation: 'update' }, ] ); } ); test( 'should drop edits already reflected in saved metadata', () => { const savedMetadata = [ { key: 'geo_latitude', value: '10' } ]; expect( getUnappliedMetadataEdits( edits, savedMetadata ) ).toEqual( [] ); } ); } ); } );