Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ export const CodeEditorShortcuts: React.FC<CodeEditorShortcutsProps> = ({ editor
const keyMapName = codeEditorInstance.codemirror.getOption('keyMap')

const combinedKeyMap: KeyMap = {
...isMacOS() ? fallbackKeyMapMac : fallbackKeyMap,
...keyMapName && getKeyMap(keyMapName),
...'object' === typeof extraKeys ? extraKeys : undefined
...'object' === typeof extraKeys ? extraKeys : undefined,
...isMacOS() ? fallbackKeyMapMac : fallbackKeyMap
}

return unpackKeyMap(combinedKeyMap)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const FilterByTagControl: React.FC<FilterByTagControlProps> = ({ visibleSnippets
<select
id={tagFilterId}
name="tag"
value={currentTag}
value={currentTag ?? ''}
aria-label={__('Filter snippets by tag', 'code-snippets')}
onChange={event => setCurrentTag(event.target.value)}
>
Expand Down
12 changes: 10 additions & 2 deletions src/js/components/ManageMenu/SnippetsTable/SnippetsTableSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { __, sprintf } from '@wordpress/i18n'
import React from 'react'
import { Button } from '../../common/Button'
import { useSnippetsFilters } from './WithSnippetsTableFilters'
import { INDEX_STATUS, useSnippetsFilters } from './WithSnippetsTableFilters'

export const SearchArea = () => {
const { searchQuery, setSearchQuery } = useSnippetsFilters()
Expand Down Expand Up @@ -30,7 +30,14 @@ export const SearchArea = () => {
}

export const SearchResultsIndicator = () => {
const { searchQueryText, searchLineNumber, currentTag, setSearchQuery, setCurrentTag } = useSnippetsFilters()
const {
searchQueryText,
searchLineNumber,
currentTag,
setCurrentStatus,
setSearchQuery,
setCurrentTag
} = useSnippetsFilters()

return searchQueryText || currentTag
? <p className="snippets-search-subtitle">
Expand All @@ -47,6 +54,7 @@ export const SearchResultsIndicator = () => {

{' '}
<Button small className="clear-filters" onClick={() => {
setCurrentStatus(INDEX_STATUS)
setSearchQuery()
setCurrentTag()
}}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,12 @@ export const useApplyBulkAction = (

case 'trash':
case 'delete':
case 'restore':
await applyAndRefresh(
allSnippets.filter(snippet => selected.has(snippet.id)),
snippet => api.delete({ id: snippet.id, network: snippet.network }),
snippet => 'restore' === action
? api.restore({ id: snippet.id, network: snippet.network })
: api.delete({ id: snippet.id, network: snippet.network }),
refreshSnippetsList)
break

Expand Down
4 changes: 2 additions & 2 deletions src/php/Flat_Files/Snippet_Files.php
Original file line number Diff line number Diff line change
Expand Up @@ -484,11 +484,11 @@ public static function get_active_snippets_from_flat_files(
'condition_id' => intval( $snippet['condition_id'] ),
];
}

self::sort_active_snippets( $active_snippets, $db );
}
}

self::sort_active_snippets( $active_snippets, $db );

return $active_snippets;
}

Expand Down
9 changes: 4 additions & 5 deletions tests/e2e/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { join } from 'path'
import { expect, test as setup } from '@playwright/test'
import { wpCli } from './helpers/wpCli'
import { URLS } from './helpers/constants'
import { TIMEOUTS, URLS } from './helpers/constants'

const authFile = join(__dirname, '.auth/user.json')
const AUTH_SETUP_TIMEOUT_MS = 120000

setup('authenticate', async ({ page }) => {
setup.setTimeout(AUTH_SETUP_TIMEOUT_MS)
setup.setTimeout(TIMEOUTS.VERY_LONG)

// Ensure a clean environment across local runs / retries.
// If Safe Mode is enabled via `wp-config.php` it disables snippet execution and can
Expand Down Expand Up @@ -60,10 +59,10 @@ setup('authenticate', async ({ page }) => {
await updateBtn.first().click()
}
// Give the upgrade process more time to complete and the admin UI to load.
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: 120000 })
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: TIMEOUTS.VERY_LONG })
} else {
// Normal path: wait for admin UI.
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: 60000 })
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: TIMEOUTS.LONG })
}

await expect(page.locator('#adminmenu')).toBeVisible()
Expand Down
70 changes: 70 additions & 0 deletions tests/e2e/code-snippets-community-featured.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ const isSnippetDownloadRequest = (url: URL): boolean =>
url.pathname.includes('/cloud/snippets/501/download') ||
true === url.searchParams.get('rest_route')?.includes('/cloud/snippets/501/download')

const isSearchRequest = (url: URL): boolean =>
(url.pathname.includes('/cloud/snippets') || true === url.searchParams.get('rest_route')?.includes('/cloud/snippets')) &&
!isFeaturedRequest(url) && !url.pathname.includes('/download') &&
!url.searchParams.get('rest_route')?.includes('/download')

const makeCloudSnippet = (id: number, name: string, localId: number | null = null) => ({
id,
slug: `mock-cloud-snippet-${id}`,
Expand Down Expand Up @@ -169,6 +174,71 @@ test.describe('Community Cloud Featured Snippets', () => {
.toContainText('An error occurred while fetching search results. Please try again.')
})

test('shows a clear empty state when a keyword search has no results', async ({ page }) => {
await page.route(isSearchRequest, route => route.fulfill({
contentType: 'application/json',
body: JSON.stringify(makeFeaturedResponse([]))
}))
await openCommunityCloud(page)

await page.getByRole('searchbox', { name: 'Search query' }).fill('no matching snippet')
await page.getByRole('button', { name: 'Search Cloud Library' }).click()
await expect(page.locator('.no-results'))
.toHaveText('No snippets could be found with that search term. Please try again.')
})

test('shows a library-specific empty state for a codevault search', async ({ page }) => {
await page.route(isSearchRequest, route => route.fulfill({
contentType: 'application/json',
body: JSON.stringify(makeFeaturedResponse([]))
}))
await openCommunityCloud(page)

await page.getByRole('combobox', { name: 'Search method' }).selectOption('codevault')
await page.getByRole('searchbox', { name: 'Search query' }).fill('missing library')
await page.getByRole('button', { name: 'Search Cloud Library' }).click()
await expect(page.locator('.no-results'))
.toHaveText('Could not find a codevault with that name. Please try again.')
})

test('shows every available cloud filter', async ({ page }) => {
await page.route(isFeaturedRequest, route => route.fulfill({
contentType: 'application/json',
body: JSON.stringify({
...makeFeaturedResponse(),
available_filters: {
categories: [{ id: 12, name: 'Utilities' }],
types: [{ id: 1, name: 'PHP' }],
statuses: [{ id: 4, name: 'Verified' }]
}
})
}))
await openCommunityCloud(page)

await expect(page.getByRole('combobox', { name: 'Snippet Category' })).toContainText('Utilities')
await expect(page.getByRole('combobox', { name: 'Snippet Type' })).toContainText('PHP')
await expect(page.getByRole('combobox', { name: 'Snippet Status' })).toContainText('Verified')
})

test('includes a chosen category in the next cloud request', async ({ page }) => {
await page.route(isFeaturedRequest, route => route.fulfill({
contentType: 'application/json',
body: JSON.stringify({
...makeFeaturedResponse(),
available_filters: { categories: [{ id: 12, name: 'Utilities' }] }
})
}))
await openCommunityCloud(page)
await expect(page.getByRole('combobox', { name: 'Snippet Category' })).toBeVisible()

const filteredRequest = page.waitForRequest(request => {
const url = new URL(request.url())
return isFeaturedRequest(url) && '12' === url.searchParams.get('category')
})
await page.getByRole('combobox', { name: 'Snippet Category' }).selectOption('12')
await filteredRequest
})

test('Shares download state between the card and its preview', async ({ page }) => {
let releaseDownload: VoidFunction = () => undefined
const downloadPending = new Promise<void>(resolve => {
Expand Down
Loading
Loading