Skip to content
Merged
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 @@ -4,7 +4,7 @@ import { CloudSubscriptionCapiService } from 'src/modules/cloud/subscription/clo
import { CreateFreeSubscriptionCloudJob } from 'src/modules/cloud/job/jobs/create-free-subscription.cloud-job';
import { CloudDatabaseCapiService } from 'src/modules/cloud/database/cloud-database.capi.service';
import { CloudJobName } from 'src/modules/cloud/job/constants';
import { CloudJobStep } from 'src/modules/cloud/job/models';
import { CloudJobStatus, CloudJobStep } from 'src/modules/cloud/job/models';
import { DatabaseService } from 'src/modules/database/database.service';
import { Database } from 'src/modules/database/models/database';
import { CloudDatabaseAnalytics } from 'src/modules/cloud/database/cloud-database.analytics';
Expand Down Expand Up @@ -54,12 +54,18 @@ export class CreateFreeSubscriptionAndDatabaseCloudJob extends CloudJob {

this.changeState({ step: CloudJobStep.Database });

return this.runChildJob(
const database = await this.runChildJob(
CreateFreeDatabaseCloudJob,
{
subscriptionId: freeSubscription.id,
},
this.options,
);

this.result = { resourceId: database.id };

this.changeState({ status: CloudJobStatus.Finished });

return database;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ const CommonAppSubscription = () => {
})

socketRef.current.on(CloudJobEvents.Monitor, (data: CloudJobInfo) => {
if ((data.name as unknown) === CloudJobName.CreateFreeDatabase) {
const jobName = data.name as unknown
if (
jobName === CloudJobName.CreateFreeDatabase
|| jobName === CloudJobName.CreateFreeSubscriptionAndDatabase
|| jobName === CloudJobName.ImportFreeDatabase) {
dispatch(setJob(data))
}
})
Expand Down
23 changes: 20 additions & 3 deletions redisinsight/ui/src/components/notifications/Notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import { IError, IMessage, InfiniteMessage } from 'uiSrc/slices/interfaces'
import { ApiEncryptionErrors } from 'uiSrc/constants/apiErrors'
import { DEFAULT_ERROR_MESSAGE } from 'uiSrc/utils'
import { showOAuthProgress } from 'uiSrc/slices/oauth/cloud'

import { CustomErrorCodes } from 'uiSrc/constants'
import { TelemetryEvent, sendEventTelemetry } from 'uiSrc/telemetry'

import errorMessages from './error-messages'
import { InfiniteMessagesIds } from './components'

Expand Down Expand Up @@ -115,9 +116,25 @@ const Notifications = () => {
text: Inner,
color: 'success',
onClose: () => {
if (id === InfiniteMessagesIds.oAuthProgress) {
dispatch(showOAuthProgress(false))
switch (id) {
case InfiniteMessagesIds.oAuthProgress:
dispatch(showOAuthProgress(false))
break
case InfiniteMessagesIds.databaseExists:
sendEventTelemetry({
event: TelemetryEvent.CLOUD_IMPORT_EXISTING_DATABASE_FORM_CLOSED,
})
break
case InfiniteMessagesIds.subscriptionExists:
sendEventTelemetry({
event: TelemetryEvent.CLOUD_CREATE_DATABASE_IN_SUBSCRIPTION_FORM_CLOSED,
})
break

default:
break
}

dispatch(removeInfiniteNotification(id))
},
toastLifeTimeMs: 3_600_000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,70 @@ describe('INFINITE_MESSAGES', () => {
})
describe('PENDING_CREATE_DB', () => {
it('should render message', () => {
const { Inner } = INFINITE_MESSAGES.PENDING_CREATE_DB
const { Inner } = INFINITE_MESSAGES.PENDING_CREATE_DB()
expect(render(<>{Inner}</>)).toBeTruthy()
})
})
describe('DATABASE_EXISTS', () => {
it('should render message', () => {
const { Inner } = INFINITE_MESSAGES.DATABASE_EXISTS(jest.fn())
expect(render(<>{Inner}</>)).toBeTruthy()
})

it('should call onSuccess', () => {
const onSuccess = jest.fn()
const { Inner } = INFINITE_MESSAGES.DATABASE_EXISTS(onSuccess)
render(<>{Inner}</>)

fireEvent.click(screen.getByTestId('import-db-sso-btn'))
fireEvent.mouseUp(screen.getByTestId('database-exists-notification'))
fireEvent.mouseDown(screen.getByTestId('database-exists-notification'))

expect(onSuccess).toBeCalled()
})

it('should call onCancel', () => {
const onSuccess = jest.fn()
const onCancel = jest.fn()
const { Inner } = INFINITE_MESSAGES.DATABASE_EXISTS(onSuccess, onCancel)
render(<>{Inner}</>)

fireEvent.click(screen.getByTestId('cancel-import-db-sso-btn'))
fireEvent.mouseUp(screen.getByTestId('database-exists-notification'))
fireEvent.mouseDown(screen.getByTestId('database-exists-notification'))

expect(onCancel).toBeCalled()
})
})
describe('SUBSCRIPTION_EXISTS', () => {
it('should render message', () => {
const { Inner } = INFINITE_MESSAGES.SUBSCRIPTION_EXISTS(jest.fn())
expect(render(<>{Inner}</>)).toBeTruthy()
})

it('should call onSuccess', () => {
const onSuccess = jest.fn()
const { Inner } = INFINITE_MESSAGES.SUBSCRIPTION_EXISTS(onSuccess)
render(<>{Inner}</>)

fireEvent.click(screen.getByTestId('create-subscription-sso-btn'))
fireEvent.mouseUp(screen.getByTestId('subscription-exists-notification'))
fireEvent.mouseDown(screen.getByTestId('subscription-exists-notification'))

expect(onSuccess).toBeCalled()
})

it('should call onCancel', () => {
const onSuccess = jest.fn()
const onCancel = jest.fn()
const { Inner } = INFINITE_MESSAGES.SUBSCRIPTION_EXISTS(onSuccess, onCancel)
render(<>{Inner}</>)

fireEvent.click(screen.getByTestId('cancel-create-subscription-sso-btn'))
fireEvent.mouseUp(screen.getByTestId('subscription-exists-notification'))
fireEvent.mouseDown(screen.getByTestId('subscription-exists-notification'))

expect(onCancel).toBeCalled()
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import { CloudJobStep } from 'uiSrc/electron/constants'
export enum InfiniteMessagesIds {
oAuthProgress = 'oAuthProgress',
oAuthSuccess = 'oAuthSuccess',
databaseExists = 'databaseExists',
subscriptionExists = 'subscriptionExists',
}

export const INFINITE_MESSAGES = {
PENDING_CREATE_DB: (step: CloudJobStep) => ({
PENDING_CREATE_DB: (step?: CloudJobStep) => ({
id: InfiniteMessagesIds.oAuthProgress,
Inner: (
<div
Expand All @@ -25,6 +27,7 @@ export const INFINITE_MESSAGES = {
{ (step === CloudJobStep.Credentials || !step) && 'Processing Cloud API keys…'}
{ step === CloudJobStep.Subscription && 'Processing Cloud subscriptions…'}
{ step === CloudJobStep.Database && 'Creating a free Cloud database…'}
{ step === CloudJobStep.Import && 'Importing a free Cloud database…'}
</span>
</EuiTitle>
<EuiText size="xs">
Expand Down Expand Up @@ -70,4 +73,84 @@ export const INFINITE_MESSAGES = {
</div>
)
}),
DATABASE_EXISTS: (onSuccess?: () => void, onClose?: () => void) => ({
id: InfiniteMessagesIds.databaseExists,
Inner: (
<div
role="presentation"
onMouseDown={(e) => { e.preventDefault() }}
onMouseUp={(e) => { e.preventDefault() }}
data-testid="database-exists-notification"
>
<EuiTitle className="infiniteMessage__title"><span>You already have a free Redis Enterprise Cloud subscription.</span></EuiTitle>
<EuiText size="xs">
Do you want to import your existing database into RedisInsight?
</EuiText>
<EuiSpacer size="m" />
<EuiFlexGroup justifyContent="spaceBetween" gutterSize="none">
<EuiFlexItem grow={false}>
<EuiButton
fill
size="s"
color="secondary"
onClick={() => onSuccess?.()}
data-testid="import-db-sso-btn"
>
Import
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
size="s"
color="secondary"
onClick={() => onClose?.()}
data-testid="cancel-import-db-sso-btn"
>
Cancel
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</div>
)
}),
SUBSCRIPTION_EXISTS: (onSuccess?: () => void, onClose?: () => void) => ({
id: InfiniteMessagesIds.subscriptionExists,
Inner: (
<div
role="presentation"
onMouseDown={(e) => { e.preventDefault() }}
onMouseUp={(e) => { e.preventDefault() }}
data-testid="subscription-exists-notification"
>
<EuiTitle className="infiniteMessage__title"><span>Your subscription does not have a free Redis Enterprise Cloud database.</span></EuiTitle>
<EuiText size="xs">
Do you want to create a free database in your existing subscription?
</EuiText>
<EuiSpacer size="m" />
<EuiFlexGroup justifyContent="spaceBetween" gutterSize="none">
<EuiFlexItem grow={false}>
<EuiButton
fill
size="s"
color="secondary"
onClick={() => onSuccess?.()}
data-testid="create-subscription-sso-btn"
>
Create
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
size="s"
color="secondary"
onClick={() => onClose?.()}
data-testid="cancel-create-subscription-sso-btn"
>
Cancel
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</div>
)
}),
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { addErrorNotification, addInfiniteNotification, removeInfiniteNotificati
import { RootState } from 'uiSrc/slices/store'
import { loadInstances } from 'uiSrc/slices/instances/instances'
import { INFINITE_MESSAGES, InfiniteMessagesIds } from 'uiSrc/components/notifications/components'
import { CustomErrorCodes } from 'uiSrc/constants'
import OAuthJobs from './OAuthJobs'

jest.mock('react-redux', () => ({
Expand Down Expand Up @@ -128,8 +129,68 @@ describe('OAuthJobs', () => {
rerender(<OAuthJobs />)

const expectedActions = [
removeInfiniteNotification(InfiniteMessagesIds.oAuthProgress),
addErrorNotification({ response: { data: error } } as AxiosError),
removeInfiniteNotification(InfiniteMessagesIds.oAuthProgress),
]
expect(clearStoreActions(store.getActions())).toEqual(
clearStoreActions(expectedActions)
)
})

it('should call addInfiniteNotification and removeInfiniteNotification when errorCode is 11_108', async () => {
const mockDatabaseId = '123'
const error = {
errorCode: CustomErrorCodes.CloudDatabaseAlreadyExistsFree,
resource: {
databaseId: mockDatabaseId
}
};
(oauthCloudJobSelector as jest.Mock).mockImplementation(() => ({
status: ''
}))

const { rerender } = render(<OAuthJobs />);

(oauthCloudJobSelector as jest.Mock).mockImplementation(() => ({
status: CloudJobStatus.Failed,
error,
}))

rerender(<OAuthJobs />)

const expectedActions = [
addInfiniteNotification(INFINITE_MESSAGES.DATABASE_EXISTS()),
removeInfiniteNotification(InfiniteMessagesIds.oAuthProgress),
]
expect(clearStoreActions(store.getActions())).toEqual(
clearStoreActions(expectedActions)
)
})

it('should call addInfiniteNotification and removeInfiniteNotification when errorCode is 11_114', async () => {
const mockDatabaseId = '123'
const error = {
errorCode: CustomErrorCodes.CloudSubscriptionAlreadyExistsFree,
resource: {
databaseId: mockDatabaseId
}
};
(oauthCloudJobSelector as jest.Mock).mockImplementation(() => ({
status: ''
}))

const { rerender } = render(<OAuthJobs />);

(oauthCloudJobSelector as jest.Mock).mockImplementation(() => ({
status: CloudJobStatus.Failed,
error,
}))

rerender(<OAuthJobs />)

const expectedActions = [
addInfiniteNotification(INFINITE_MESSAGES.DATABASE_EXISTS()),
removeInfiniteNotification(InfiniteMessagesIds.oAuthProgress),
]
expect(clearStoreActions(store.getActions())).toEqual(
clearStoreActions(expectedActions)
Expand Down
Loading