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 @@ -51,13 +51,14 @@
const onQueryChange = (term: string) => {
const value = term?.toLowerCase()

const itemsTemp = instances.filter(
(item: InstanceRedisCloud) =>
item.name?.toLowerCase().indexOf(value) !== -1 ||
(item.publicEndpoint || '')?.toLowerCase().indexOf(value) !== -1 ||
item.subscriptionId?.toString()?.indexOf(value) !== -1 ||
item.subscriptionName?.toLowerCase().indexOf(value) !== -1 ||
item.databaseId?.toString()?.indexOf(value) !== -1,
item.databaseId?.toString()?.indexOf(value) !== -1 ||
(item.statusAdded || '').toLowerCase().indexOf(value) !== -1,

Check warning on line 61 in redisinsight/ui/src/pages/autodiscover-cloud/redis-cloud-databases-result/RedisCloudDatabasesResult.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 61 in redisinsight/ui/src/pages/autodiscover-cloud/redis-cloud-databases-result/RedisCloudDatabasesResult.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

Check warning on line 61 in redisinsight/ui/src/pages/autodiscover-cloud/redis-cloud-databases-result/RedisCloudDatabasesResult.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

Check warning on line 61 in redisinsight/ui/src/pages/autodiscover-cloud/redis-cloud-databases-result/RedisCloudDatabasesResult.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
)

Check warning on line 62 in redisinsight/ui/src/pages/autodiscover-cloud/redis-cloud-databases-result/RedisCloudDatabasesResult.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

if (!itemsTemp.length) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,192 @@
import React from 'react'
import { instance, mock } from 'ts-mockito'
import { faker } from '@faker-js/faker'
import {
RedisCloudSubscription,
RedisCloudSubscriptionStatus,
RedisCloudSubscriptionType,
} from 'uiSrc/slices/interfaces'
import { render } from 'uiSrc/utils/test-utils'
import { fireEvent, render, screen, waitFor } from 'uiSrc/utils/test-utils'
import RedisCloudSubscriptions, { Props } from './RedisCloudSubscriptions'

const mockedProps = mock<Props>()

const columnsMock = [
{
id: 'name',
accessorKey: 'name',
header: 'Name',
enableSorting: true,
},
{
id: 'id',
accessorKey: 'id',
header: 'Subscription ID',
enableSorting: true,
},
]

const createSubscription = (
overrides?: Partial<RedisCloudSubscription>,
): RedisCloudSubscription => ({
id: faker.number.int(),
name: faker.company.name(),
numberOfDatabases: faker.number.int({ min: 1, max: 10 }),
provider: faker.helpers.arrayElement(['AWS', 'GCP', 'Azure']),
region: faker.helpers.arrayElement(['us-east-1', 'eu-west-1', 'ap-south-1']),
status: RedisCloudSubscriptionStatus.Active,
type: RedisCloudSubscriptionType.Fixed,
free: faker.datatype.boolean(),
...overrides,
})

describe('RedisCloudSubscriptions', () => {
const defaultProps: Partial<Props> = {
columns: columnsMock,
subscriptions: [],
selection: [],
loading: false,
account: null,
error: '',
onClose: jest.fn(),
onBack: jest.fn(),
onSubmit: jest.fn(),
onSelectionChange: jest.fn(),
}

const renderComponent = (propsOverride?: Partial<Props>) => {
const props = { ...defaultProps, ...propsOverride } as Props
return render(
<RedisCloudSubscriptions {...instance(mockedProps)} {...props} />,
)
}

it('should render', () => {
const columnsMock = [
{
id: 'subscriptionId',
accessorKey: 'subscriptionId',
header: 'Subscription ID',
enableSorting: true,
},
]
const subscriptionsMock: RedisCloudSubscription[] = [createSubscription()]
expect(renderComponent({ subscriptions: subscriptionsMock })).toBeTruthy()
})

const subscriptionsMock: RedisCloudSubscription[] = [
{
id: 123,
name: 'name',
numberOfDatabases: 123,
provider: 'provider',
region: 'region',
describe('search functionality', () => {
const subscriptions: RedisCloudSubscription[] = [
createSubscription({
id: 111,
name: 'Production Database',
provider: 'AWS',
region: 'us-east-1',
status: RedisCloudSubscriptionStatus.Active,
type: RedisCloudSubscriptionType.Flexible,
}),
createSubscription({
id: 222,
name: 'Staging Environment',
provider: 'GCP',
region: 'eu-west-1',
status: RedisCloudSubscriptionStatus.Active,
type: RedisCloudSubscriptionType.Fixed,
free: false,
},
}),
createSubscription({
id: 333,
name: 'Development',
provider: 'Azure',
region: 'ap-south-1',
status: RedisCloudSubscriptionStatus.Error,
type: RedisCloudSubscriptionType.Fixed,
}),
]
expect(
render(
<RedisCloudSubscriptions
{...instance(mockedProps)}
columns={columnsMock}
subscriptions={subscriptionsMock}
/>,
),
).toBeTruthy()

it('should filter by name', async () => {
renderComponent({ subscriptions })

const searchInput = screen.getByTestId('search')
fireEvent.change(searchInput, { target: { value: 'Production' } })

await waitFor(() => {
expect(screen.getByText('Production Database')).toBeInTheDocument()
expect(
screen.queryByText('Staging Environment'),
).not.toBeInTheDocument()
})
})

it('should filter by id', async () => {
renderComponent({ subscriptions })

const searchInput = screen.getByTestId('search')
fireEvent.change(searchInput, { target: { value: '222' } })

await waitFor(() => {
expect(screen.getByText('Staging Environment')).toBeInTheDocument()
expect(
screen.queryByText('Production Database'),
).not.toBeInTheDocument()
})
})

it('should filter by provider', async () => {
renderComponent({ subscriptions })

const searchInput = screen.getByTestId('search')
fireEvent.change(searchInput, { target: { value: 'AWS' } })

await waitFor(() => {
expect(screen.getByText('Production Database')).toBeInTheDocument()
expect(
screen.queryByText('Staging Environment'),
).not.toBeInTheDocument()
})
})

it('should filter by region', async () => {
renderComponent({ subscriptions })

const searchInput = screen.getByTestId('search')
fireEvent.change(searchInput, { target: { value: 'eu-west' } })

await waitFor(() => {
expect(screen.getByText('Staging Environment')).toBeInTheDocument()
expect(
screen.queryByText('Production Database'),
).not.toBeInTheDocument()
})
})

it('should filter by status', async () => {
renderComponent({ subscriptions })

const searchInput = screen.getByTestId('search')
fireEvent.change(searchInput, { target: { value: 'error' } })

await waitFor(() => {
expect(screen.getByText('Development')).toBeInTheDocument()
expect(
screen.queryByText('Production Database'),
).not.toBeInTheDocument()
})
})

it('should filter by type', async () => {
renderComponent({ subscriptions })

const searchInput = screen.getByTestId('search')
fireEvent.change(searchInput, { target: { value: 'flexible' } })

await waitFor(() => {
expect(screen.getByText('Production Database')).toBeInTheDocument()
expect(
screen.queryByText('Staging Environment'),
).not.toBeInTheDocument()
})
})

it('should be case-insensitive', async () => {
renderComponent({ subscriptions })

const searchInput = screen.getByTestId('search')
fireEvent.change(searchInput, { target: { value: 'PRODUCTION' } })

await waitFor(() => {
expect(screen.getByText('Production Database')).toBeInTheDocument()
})
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,15 @@ const RedisCloudSubscriptions = ({
}
}, [subscriptions, loading])

const countStatusActive = items.filter(
({ status, numberOfDatabases }: RedisCloudSubscription) =>
status === RedisCloudSubscriptionStatus.Active && numberOfDatabases !== 0,
)?.length
// Calculate counts from original subscriptions to prevent notification re-triggering on search
const countStatusActive =
subscriptions?.filter(
({ status, numberOfDatabases }: RedisCloudSubscription) =>
status === RedisCloudSubscriptionStatus.Active &&
numberOfDatabases !== 0,
)?.length || 0

const countStatusFailed = items.length - countStatusActive
const countStatusFailed = (subscriptions?.length || 0) - countStatusActive

const handleSubmit = () => {
onSubmit(
Expand All @@ -106,7 +109,11 @@ const RedisCloudSubscriptions = ({
subscriptions?.filter(
(item: RedisCloudSubscription) =>
item.name?.toLowerCase()?.indexOf(value) !== -1 ||
item.id?.toString()?.toLowerCase().indexOf(value) !== -1,
item.id?.toString()?.indexOf(value) !== -1 ||
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering can't we add such util:

export const filterBySearchTerm = <T extends Record<string, unknown>>(
  items: T[],
  searchTerm: string,
  fields: (keyof T)[],
): T[] => {
  const term = searchTerm.toLowerCase()
  
  return items.filter((item) =>
    fields.some((field) => {
      const value = item[field]
      return String(value ?? '').toLowerCase().includes(term)
    }),
  )
}


or

export const matchesSearch = (
  fieldValue: unknown,
  searchTerm: string, // expected to be already lowercased
): boolean => String(fieldValue ?? '').toLowerCase().includes(searchTerm)

and then this syntax would be easier to be read and moreover we have it in the RedisCloudDatabasesResult.tsx as well.

Maybe not for this PR, but actually, why not 😸

item.type?.toLowerCase()?.indexOf(value) !== -1 ||
item.provider?.toLowerCase()?.indexOf(value) !== -1 ||
item.region?.toLowerCase()?.indexOf(value) !== -1 ||
item.status?.toLowerCase()?.indexOf(value) !== -1,
) ?? []

if (!itemsTemp?.length) {
Expand Down
Loading