From 885c14563cc5877df7768605cee0d2bcd745c70f Mon Sep 17 00:00:00 2001 From: Rami Yushuvaev Date: Wed, 9 Sep 2026 14:01:22 +0300 Subject: [PATCH 1/2] feat: add tags cloud view and update related components --- src/css/insights.scss | 16 ++++ .../InsightsMenu/InsightsChartViewToggle.tsx | 44 ++++++---- .../InsightsMenu/InsightsCharts.tsx | 37 +++++++- .../InsightsMenu/InsightsDashboard.tsx | 88 +++++++++++-------- src/js/types/Insights.ts | 4 +- .../Insights_View_Rest_Controller.php | 15 +++- tests/e2e/code-snippets-insights.spec.ts | 30 ++++--- .../Insights_View_Rest_Controller_Test.php | 2 + 8 files changed, 162 insertions(+), 74 deletions(-) diff --git a/src/css/insights.scss b/src/css/insights.scss index fd40dc38c..7f1f4c46f 100644 --- a/src/css/insights.scss +++ b/src/css/insights.scss @@ -14,6 +14,7 @@ } .insights-chart-card { + min-block-size: 220px; box-sizing: border-box; border: 1px solid var(--cs-color-border-subtle); border-radius: var(--cs-card-radius); @@ -115,6 +116,21 @@ list-style: none; } +.insights-tags-cloud { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 8px 12px; + padding: 0; + margin: 0; + list-style: none; + + li { + margin: 0; + line-height: 1.4; + } +} + .insights-chart-entry-link { color: var(--cs-color-text); text-decoration: none; diff --git a/src/js/components/InsightsMenu/InsightsChartViewToggle.tsx b/src/js/components/InsightsMenu/InsightsChartViewToggle.tsx index cefdcde7a..2b2afd444 100644 --- a/src/js/components/InsightsMenu/InsightsChartViewToggle.tsx +++ b/src/js/components/InsightsMenu/InsightsChartViewToggle.tsx @@ -4,11 +4,12 @@ import React from 'react' import type { InsightsChartView } from '../../types/Insights' interface ViewToggleButtonProps extends InsightsChartViewToggleProps { + icon: string label: string currentView: InsightsChartView } -const ViewToggleButton: React.FC = ({ title, label, view, setView, currentView }) => +const ViewToggleButton: React.FC = ({ icon, title, label, view, setView, currentView }) => @@ -24,27 +25,38 @@ export interface InsightsChartViewToggleProps { title: string view: InsightsChartView setView: (view: InsightsChartView) => void + views?: readonly InsightsChartView[] } -export const InsightsChartViewToggle: React.FC = ({ title, view, setView }) => +const VIEW_OPTIONS: Readonly> = { + pie: { + icon: 'chart-pie', + label: __('Chart view', 'code-snippets'), + title: __('Switch to chart view', 'code-snippets') + }, + bar: { + icon: 'chart-bar', + label: __('List view', 'code-snippets'), + title: __('Switch to list view', 'code-snippets') + }, + cloud: { + icon: 'cloud', + label: __('Tags cloud view', 'code-snippets'), + title: __('Switch to tags cloud view', 'code-snippets') + } +} + +export const InsightsChartViewToggle: React.FC = ({ title, view, setView, views = ['pie', 'bar'] }) =>
- - - + />)}
diff --git a/src/js/components/InsightsMenu/InsightsCharts.tsx b/src/js/components/InsightsMenu/InsightsCharts.tsx index bcb19df38..c7d11a836 100644 --- a/src/js/components/InsightsMenu/InsightsCharts.tsx +++ b/src/js/components/InsightsMenu/InsightsCharts.tsx @@ -1,3 +1,4 @@ +import { _n, sprintf } from '@wordpress/i18n' import classnames from 'classnames' import React, { useMemo } from 'react' import { InsightsChartViewToggle } from './InsightsChartViewToggle' @@ -7,6 +8,10 @@ const PERCENTAGE_MAX = 100 const DEFAULT_COLOR = '#646970' +const TAG_CLOUD_MIN_FONT_SIZE = 0.875 + +const TAG_CLOUD_FONT_SIZE_RANGE = 0.625 + const getPieBackground = ( entries: Readonly>, colors: Readonly> | undefined, @@ -87,6 +92,28 @@ const PieChart: React.FC = ({ colors, entries }) => { ) } +const TagCloud: React.FC = ({ entries }) => { + const largestCount = useMemo(() => + Math.max(1, ...Object.values(entries).map(entry => Number(entry.count))), + [entries]) + + return ( +
    + {Object.entries(entries).map(([key, entry]) => +
  • + + {sprintf( + _n(' (%s snippet)', ' (%s snippets)', Number(entry.count), 'code-snippets'), + entry.count + )} +
  • )} +
+ ) +} + export interface InsightsChartProps { chart: InsightsChartKey entries: Readonly> @@ -94,6 +121,7 @@ export interface InsightsChartProps { view: InsightsChartView setView?: (view: InsightsChartView) => void colors?: Readonly> + views?: readonly InsightsChartView[] } export const InsightsChart: React.FC = ({ @@ -102,7 +130,8 @@ export const InsightsChart: React.FC = ({ entries, setView, title, - view + view, + views }) =>
= ({ >

{title}

- {setView && } + {setView && }
{'bar' === view ? - : } + : 'pie' === view + ? + : }
export interface TotalsInsightsChartProps extends InsightsChartEntry { diff --git a/src/js/components/InsightsMenu/InsightsDashboard.tsx b/src/js/components/InsightsMenu/InsightsDashboard.tsx index 08837aeae..926fcc4e5 100644 --- a/src/js/components/InsightsMenu/InsightsDashboard.tsx +++ b/src/js/components/InsightsMenu/InsightsDashboard.tsx @@ -12,7 +12,8 @@ export const DEFAULT_INSIGHTS_CHART_VIEWS: InsightsChartViews = window.CODE_SNIP type: 'bar', activation: 'pie', conditions: 'pie', - location: 'bar' + location: 'bar', + tags: 'bar' } export const INSIGHTS_TYPE_COLORS: Readonly> = { @@ -119,7 +120,7 @@ const LocationChart = ({ summary, view, setView }: ConfigurableChartProps) => { ) } -const TagsChart: React.FC = ({ summary }) => +const TagsChart: React.FC = ({ summary, view, setView }) => = ({ summary }) => Object.entries(summary.tagCounts).map(([tag, entry]) => [tag, { ...entry, url: buildUrl(window.CODE_SNIPPETS?.urls.manage, { tag }) }]) )} - view="bar" + view={view} + setView={setView} + views={['bar', 'cloud']} /> export interface InsightsDashboardProps { summary: InsightsSummary } +interface InsightsChartGridProps { + summary: InsightsSummary + chartViews: InsightsChartViews + setChartView: (chart: InsightsConfigurableChartKey, view: InsightsChartView) => void +} + +const InsightsChartGrid: React.FC = ({ summary, chartViews, setChartView }) => +
+ + + setChartView('type', view)} + /> + + setChartView('activation', view)} + /> + + setChartView('conditions', view)} + /> + + setChartView('location', view)} + /> + + setChartView('tags', view)} + /> +
+ export const InsightsDashboard: React.FC = ({ summary }) => { const { api } = useRestAPI() const [chartViews, setChartViews] = useState(DEFAULT_INSIGHTS_CHART_VIEWS) @@ -157,38 +205,6 @@ export const InsightsDashboard: React.FC = ({ summary })
-
- - - updateChartView('type', view)} - /> - - updateChartView('activation', view)} - /> - - updateChartView('conditions', view)} - /> - - updateChartView('location', view)} - /> - - -
+ } diff --git a/src/js/types/Insights.ts b/src/js/types/Insights.ts index 6788c8b88..f35ff6e7c 100644 --- a/src/js/types/Insights.ts +++ b/src/js/types/Insights.ts @@ -2,9 +2,9 @@ import type { SnippetScope, SnippetType } from './Snippet' export type InsightsChartKey = 'total' | InsightsConfigurableChartKey | 'tags' -export type InsightsConfigurableChartKey = 'type' | 'activation' | 'conditions' | 'location' +export type InsightsConfigurableChartKey = 'type' | 'activation' | 'conditions' | 'location' | 'tags' -export type InsightsChartView = 'pie' | 'bar' +export type InsightsChartView = 'pie' | 'bar' | 'cloud' export type InsightsChartViews = Readonly> diff --git a/src/php/REST_API/Preferences/Insights_View_Rest_Controller.php b/src/php/REST_API/Preferences/Insights_View_Rest_Controller.php index 2d10bf01b..4de3b6b33 100644 --- a/src/php/REST_API/Preferences/Insights_View_Rest_Controller.php +++ b/src/php/REST_API/Preferences/Insights_View_Rest_Controller.php @@ -32,12 +32,18 @@ final class Insights_View_Rest_Controller extends Preference_REST_Controller { /** * Insights charts with independently configurable views. */ - public const CHART_KEYS = [ 'type', 'activation', 'conditions', 'location' ]; + public const CHART_KEYS = [ 'type', 'activation', 'conditions', 'location', 'tags' ]; /** * Valid Insights chart view values. */ - public const CHART_VIEWS = [ 'pie', 'bar' ]; + public const CHART_VIEWS = [ + 'type' => [ 'pie', 'bar' ], + 'activation' => [ 'pie', 'bar' ], + 'conditions' => [ 'pie', 'bar' ], + 'location' => [ 'pie', 'bar' ], + 'tags' => [ 'bar', 'cloud' ], + ]; /** * The Insights chart views shown when no preference has been saved. @@ -47,6 +53,7 @@ final class Insights_View_Rest_Controller extends Preference_REST_Controller { 'activation' => 'pie', 'conditions' => 'pie', 'location' => 'bar', + 'tags' => 'bar', ]; /** @@ -65,7 +72,7 @@ public static function get_insights_chart_views(): array { self::CHART_KEYS, static function ( array $normalized, string $key ) use ( $views ): array { $view = $views[ $key ] ?? self::DEFAULT_VIEWS[ $key ]; - $normalized[ $key ] = in_array( $view, self::CHART_VIEWS, true ) + $normalized[ $key ] = in_array( $view, self::CHART_VIEWS[ $key ], true ) ? $view : self::DEFAULT_VIEWS[ $key ]; @@ -118,7 +125,7 @@ public function validate_insights_chart_views( $views ): bool { $view = $views[ $key ]; - if ( ! in_array( $view, self::CHART_VIEWS, true ) ) { + if ( ! in_array( $view, self::CHART_VIEWS[ $key ], true ) ) { return false; } } diff --git a/tests/e2e/code-snippets-insights.spec.ts b/tests/e2e/code-snippets-insights.spec.ts index 800e20538..9f632937c 100644 --- a/tests/e2e/code-snippets-insights.spec.ts +++ b/tests/e2e/code-snippets-insights.spec.ts @@ -116,16 +116,11 @@ test.describe('Insights screen', () => { await expect(withoutConditions.locator('strong')).toHaveText('4') }) - test('shows used tags in a fixed bar chart', async ({ page }) => { + test('switches used tags between bar and cloud views', async ({ page }) => { await SnippetsTestHelper.createSnippetViaCli({ - name: 'Insights Shared and Alpha Tags', + name: 'Insights Shared Tag', active: true, - tags: ['Shared', 'Alpha', 'Shared'] - }) - await SnippetsTestHelper.createSnippetViaCli({ - name: 'Insights Shared and Beta Tags', - active: true, - tags: ['Shared', 'Beta'] + tags: ['Shared'] }) await page.goto(URLS.SNIPPETS_ADMIN.replace('page=snippets', 'page=code-snippets-insights')) @@ -134,11 +129,20 @@ test.describe('Insights screen', () => { await expect(page.getByRole('heading', { name: 'Tags' })).toBeVisible() await expect(tagsChart).toHaveAttribute('data-view', 'bar') await expect(tagsChart.locator('.insights-bar-chart')).toContainText('Shared') - await expect(tagsChart.locator('.insights-bar-chart')).toContainText('2') - await expect(tagsChart.locator('.insights-bar-chart')).toContainText('Alpha') - await expect(tagsChart.locator('.insights-bar-chart')).toContainText('Beta') - await expect(tagsChart.locator('.insights-chart-view-toggle')).toHaveCount(0) - await expect(tagsChart.locator('.insights-pie-chart')).toHaveCount(0) + await expect(tagsChart.getByRole('button', { name: 'Tags cloud view' })).toBeVisible() + + const response = page.waitForResponse(request => + 'POST' === request.request().method() && request.url().includes('/preferences/insights-chart-views') + ) + await tagsChart.getByRole('button', { name: 'Tags cloud view' }).click() + await response + + await expect(tagsChart).toHaveAttribute('data-view', 'cloud') + await expect(tagsChart.locator('.insights-tags-cloud')).toContainText('Shared') + await expect(tagsChart.locator('.insights-bar-chart')).toHaveCount(0) + + await page.reload() + await expect(tagsChart).toHaveAttribute('data-view', 'cloud') }) test('links chart entries to their filtered snippet lists', async ({ page, baseURL }) => { diff --git a/tests/unit/REST_API/Preferences/Insights_View_Rest_Controller_Test.php b/tests/unit/REST_API/Preferences/Insights_View_Rest_Controller_Test.php index 5e81b37ed..cb4667fd2 100644 --- a/tests/unit/REST_API/Preferences/Insights_View_Rest_Controller_Test.php +++ b/tests/unit/REST_API/Preferences/Insights_View_Rest_Controller_Test.php @@ -94,6 +94,7 @@ public function test_insights_chart_views_update_persists() { 'activation' => 'bar', 'conditions' => 'bar', 'location' => 'pie', + 'tags' => 'cloud', ]; $response = $this->dispatch( 'POST', [ 'views' => $views ] ); @@ -133,6 +134,7 @@ public function test_incomplete_stored_insights_chart_views_are_normalized() { 'activation' => 'pie', 'conditions' => 'pie', 'location' => 'bar', + 'tags' => 'bar', ], Insights_View_Rest_Controller::get_insights_chart_views() ); From 6e64ed6e002ad4287f51f18cef38321e799dc783 Mon Sep 17 00:00:00 2001 From: Rami Yushuvaev Date: Wed, 9 Sep 2026 15:04:17 +0300 Subject: [PATCH 2/2] refactor: enhance type safety for Insights chart views and update related components --- .../InsightsMenu/InsightsChartViewToggle.tsx | 20 ++-- .../InsightsMenu/InsightsCharts.tsx | 16 +-- .../InsightsMenu/InsightsDashboard.tsx | 108 ++++++++---------- src/js/types/Insights.ts | 10 +- .../Insights_View_Rest_Controller.php | 2 +- tests/e2e/code-snippets-insights.spec.ts | 20 +++- .../Insights_View_Rest_Controller_Test.php | 12 ++ 7 files changed, 106 insertions(+), 82 deletions(-) diff --git a/src/js/components/InsightsMenu/InsightsChartViewToggle.tsx b/src/js/components/InsightsMenu/InsightsChartViewToggle.tsx index 2b2afd444..40b96b1ac 100644 --- a/src/js/components/InsightsMenu/InsightsChartViewToggle.tsx +++ b/src/js/components/InsightsMenu/InsightsChartViewToggle.tsx @@ -3,13 +3,15 @@ import classnames from 'classnames' import React from 'react' import type { InsightsChartView } from '../../types/Insights' -interface ViewToggleButtonProps extends InsightsChartViewToggleProps { +interface ViewToggleButtonProps extends InsightsChartViewToggleProps { icon: string label: string - currentView: InsightsChartView + currentView: View } -const ViewToggleButton: React.FC = ({ icon, title, label, view, setView, currentView }) => +const ViewToggleButton = ( + { icon, title, label, view, setView, currentView }: ViewToggleButtonProps +) => -export interface InsightsChartViewToggleProps { +export interface InsightsChartViewToggleProps { title: string - view: InsightsChartView - setView: (view: InsightsChartView) => void - views?: readonly InsightsChartView[] + view: View + setView: (view: View) => void + views: readonly View[] } const VIEW_OPTIONS: Readonly> = { @@ -46,7 +48,9 @@ const VIEW_OPTIONS: Readonly = ({ title, view, setView, views = ['pie', 'bar'] }) => +export const InsightsChartViewToggle = ( + { title, view, setView, views }: InsightsChartViewToggleProps +) =>
= ({ entries }) => { ) } -export interface InsightsChartProps { - chart: InsightsChartKey +export interface InsightsChartProps { + chart: Chart entries: Readonly> title: string - view: InsightsChartView - setView?: (view: InsightsChartView) => void + view: InsightsChartViews[Chart] + setView?: (view: InsightsChartViews[Chart]) => void colors?: Readonly> - views?: readonly InsightsChartView[] + views: readonly InsightsChartViews[Chart][] } -export const InsightsChart: React.FC = ({ +export const InsightsChart = ({ chart, colors, entries, @@ -132,7 +132,7 @@ export const InsightsChart: React.FC = ({ title, view, views -}) => +}: InsightsChartProps) =>
void +interface ConfigurableChartProps extends StaticChartProps { + view: InsightsChartViews[Chart] + setView: (view: InsightsChartViews[Chart]) => void } -const SnippetTypeChart: React.FC = ({ summary, view, setView }) => +const SnippetTypeChart: React.FC> = ({ summary, view, setView }) => = ({ summary, view, set [type, { ...entry, url: buildUrl(window.CODE_SNIPPETS?.urls.manage, { subpage: 'snippets', type }) }]) )} colors={INSIGHTS_TYPE_COLORS} + views={['pie', 'bar']} view={view} setView={setView} /> -const ActivationStatusChart: React.FC = ({ summary, view, setView }) => +const ActivationStatusChart: React.FC> = ({ summary, view, setView }) => = ({ summary, view } }} colors={INSIGHTS_ACTIVATION_COLORS} + views={['pie', 'bar']} view={view} setView={setView} /> -const ConditionUsageChart: React.FC = ({ summary, view, setView }) => +const ConditionUsageChart: React.FC> = ({ summary, view, setView }) => -const LocationChart = ({ summary, view, setView }: ConfigurableChartProps) => { +const LocationChart = ({ summary, view, setView }: ConfigurableChartProps<'location'>) => { const entries: Record = Object.fromEntries( Object.entries(summary.locationCounts).map(([scope, count]) => [scope, { label: SNIPPET_SCOPE_DESCRIPTIONS[scope as SnippetCodeScope], count }]) @@ -114,13 +117,14 @@ const LocationChart = ({ summary, view, setView }: ConfigurableChartProps) => { title={__('Location', 'code-snippets')} entries={entries} colors={INSIGHTS_LOCATION_COLORS} + views={['pie', 'bar']} view={view} setView={setView} /> ) } -const TagsChart: React.FC = ({ summary, view, setView }) => +const TagsChart: React.FC> = ({ summary, view, setView }) => = ({ summary, view, setView }) Object.entries(summary.tagCounts).map(([tag, entry]) => [tag, { ...entry, url: buildUrl(window.CODE_SNIPPETS?.urls.manage, { tag }) }]) )} + views={['bar', 'cloud']} view={view} setView={setView} - views={['bar', 'cloud']} /> export interface InsightsDashboardProps { summary: InsightsSummary } -interface InsightsChartGridProps { - summary: InsightsSummary - chartViews: InsightsChartViews - setChartView: (chart: InsightsConfigurableChartKey, view: InsightsChartView) => void -} - -const InsightsChartGrid: React.FC = ({ summary, chartViews, setChartView }) => -
- - - setChartView('type', view)} - /> - - setChartView('activation', view)} - /> - - setChartView('conditions', view)} - /> - - setChartView('location', view)} - /> - - setChartView('tags', view)} - /> -
- export const InsightsDashboard: React.FC = ({ summary }) => { const { api } = useRestAPI() const [chartViews, setChartViews] = useState(DEFAULT_INSIGHTS_CHART_VIEWS) - - const updateChartView = (chart: InsightsConfigurableChartKey, view: InsightsChartView) => { - const views = { ...chartViews, [chart]: view } + const updateChartView = (chart: Chart, view: InsightsChartViews[Chart]) => { + const views: InsightsChartViews = { ...chartViews, [chart]: view } setChartViews(views) @@ -205,6 +163,38 @@ export const InsightsDashboard: React.FC = ({ summary })
- +
+ + + updateChartView('type', view)} + /> + + updateChartView('activation', view)} + /> + + updateChartView('conditions', view)} + /> + + updateChartView('location', view)} + /> + + updateChartView('tags', view)} + /> +
} diff --git a/src/js/types/Insights.ts b/src/js/types/Insights.ts index f35ff6e7c..a33265c26 100644 --- a/src/js/types/Insights.ts +++ b/src/js/types/Insights.ts @@ -1,12 +1,18 @@ import type { SnippetScope, SnippetType } from './Snippet' -export type InsightsChartKey = 'total' | InsightsConfigurableChartKey | 'tags' +export type InsightsChartKey = 'total' | InsightsConfigurableChartKey export type InsightsConfigurableChartKey = 'type' | 'activation' | 'conditions' | 'location' | 'tags' export type InsightsChartView = 'pie' | 'bar' | 'cloud' -export type InsightsChartViews = Readonly> +export type InsightsChartViews = Readonly<{ + type: 'pie' | 'bar' + activation: 'pie' | 'bar' + conditions: 'pie' | 'bar' + location: 'pie' | 'bar' + tags: 'bar' | 'cloud' +}> export interface InsightsChartEntry { readonly label: string diff --git a/src/php/REST_API/Preferences/Insights_View_Rest_Controller.php b/src/php/REST_API/Preferences/Insights_View_Rest_Controller.php index 4de3b6b33..ad2fa9b6f 100644 --- a/src/php/REST_API/Preferences/Insights_View_Rest_Controller.php +++ b/src/php/REST_API/Preferences/Insights_View_Rest_Controller.php @@ -99,7 +99,7 @@ protected function get_option_value(): array { */ protected function get_update_request_schema(): array { return [ - 'description' => esc_html__( 'Pie or bar view for each Insights chart.', 'code-snippets' ), + 'description' => esc_html__( 'Supported chart-specific view for each Insights chart; tags also supports the cloud view.', 'code-snippets' ), 'type' => 'object', 'required' => true, 'validate_callback' => [ $this, 'validate_insights_chart_views' ], diff --git a/tests/e2e/code-snippets-insights.spec.ts b/tests/e2e/code-snippets-insights.spec.ts index 9f632937c..5502cd48c 100644 --- a/tests/e2e/code-snippets-insights.spec.ts +++ b/tests/e2e/code-snippets-insights.spec.ts @@ -117,6 +117,11 @@ test.describe('Insights screen', () => { }) test('switches used tags between bar and cloud views', async ({ page }) => { + await SnippetsTestHelper.createSnippetViaCli({ + name: 'Insights Shared and Alpha Tags', + active: true, + tags: ['Shared', 'Alpha'] + }) await SnippetsTestHelper.createSnippetViaCli({ name: 'Insights Shared Tag', active: true, @@ -138,7 +143,14 @@ test.describe('Insights screen', () => { await response await expect(tagsChart).toHaveAttribute('data-view', 'cloud') - await expect(tagsChart.locator('.insights-tags-cloud')).toContainText('Shared') + const tagCloud = tagsChart.locator('.insights-tags-cloud') + const sharedTag = tagCloud.locator('li').filter({ hasText: /^Shared/ }) + const alphaTag = tagCloud.locator('li').filter({ hasText: /^Alpha/ }) + + await expect(sharedTag).toHaveAccessibleName('Shared (2 snippets)') + await expect(alphaTag).toHaveAccessibleName('Alpha (1 snippet)') + expect(await sharedTag.evaluate(element => Number.parseFloat(getComputedStyle(element).fontSize))) + .toBeGreaterThan(await alphaTag.evaluate(element => Number.parseFloat(getComputedStyle(element).fontSize))) await expect(tagsChart.locator('.insights-bar-chart')).toHaveCount(0) await page.reload() @@ -251,7 +263,7 @@ test.describe('Insights screen', () => { await route.fulfill({ status: 500, body: JSON.stringify({ message: 'Save failed' }) }) }) - await conditionsChart.getByRole('button', { name: 'Bar chart view' }).click() + await conditionsChart.getByRole('button', { name: 'List view' }).click() await expect(conditionsChart).toHaveAttribute('data-view', 'pie') }) @@ -281,13 +293,13 @@ test.describe('Insights screen', () => { await route.fulfill({ status: 200, body: JSON.stringify({ views }) }) }) - await typeChart.getByRole('button', { name: 'Pie chart view' }).click() + await typeChart.getByRole('button', { name: 'Chart view' }).click() await firstRequestStarted const successfulResponse = page.waitForResponse(response => 'POST' === response.request().method() && 200 === response.status() ) - await activationChart.getByRole('button', { name: 'Bar chart view' }).click() + await activationChart.getByRole('button', { name: 'List view' }).click() await successfulResponse if (undefined === rejectFirstRequest) { diff --git a/tests/unit/REST_API/Preferences/Insights_View_Rest_Controller_Test.php b/tests/unit/REST_API/Preferences/Insights_View_Rest_Controller_Test.php index cb4667fd2..eec694000 100644 --- a/tests/unit/REST_API/Preferences/Insights_View_Rest_Controller_Test.php +++ b/tests/unit/REST_API/Preferences/Insights_View_Rest_Controller_Test.php @@ -119,6 +119,18 @@ public function test_invalid_insights_chart_views_are_rejected() { ); $this->assertSame( 400, $response->get_status() ); + + foreach ( + [ + array_merge( Insights_View_Rest_Controller::DEFAULT_VIEWS, [ 'type' => 'cloud' ] ), + array_merge( Insights_View_Rest_Controller::DEFAULT_VIEWS, [ 'tags' => 'pie' ] ), + ] as $views + ) { + $response = $this->dispatch( 'POST', [ 'views' => $views ] ); + + $this->assertSame( 400, $response->get_status() ); + } + $this->assertFalse( get_option( Insights_View_Rest_Controller::OPTION_NAME ) ); }