Skip to content

Commit 024c472

Browse files
authored
RI-6635: Add cloud provider region selection (#257)
* enhance the store to support the plan logic (for selecting region and provider) * create the oauth select plan component * enable the checkbox which unlocks the select plan functionality * open the oauth select plan dialog, when isRecommended checkbox is not checked
1 parent 7db7fd5 commit 024c472

File tree

20 files changed

+814
-17
lines changed

20 files changed

+814
-17
lines changed

l10n/bundle.l10n.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,5 +363,11 @@
363363
"Auto Refresh": "Auto Refresh",
364364
"Add": "Add",
365365
"Release Notes": "Release Notes",
366-
"Redis for VS Code extension updated to {0}.": "Redis for VS Code extension updated to {0}."
366+
"Redis for VS Code extension updated to {0}.": "Redis for VS Code extension updated to {0}.",
367+
"Choose a cloud vendor": "Choose a cloud vendor",
368+
"Select a cloud vendor and region to complete the final step towards your free Redis database.": "Select a cloud vendor and region to complete the final step towards your free Redis database.",
369+
"No credit card is required.": "No credit card is required.",
370+
"Region": "Region",
371+
"No regions available, try another vendor.": "No regions available, try another vendor.",
372+
"Create database": "Create database"
367373
}

src/webviews/src/actions/oauthCallback.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { CloudAuthStatus, CloudJobName, CloudJobStep, OAuthSocialAction, Storage
33
import { CustomError } from 'uiSrc/interfaces'
44
import { CloudAuthResponse } from 'uiSrc/modules/oauth/interfaces'
55
import { localStorageService } from 'uiSrc/services'
6-
import { createFreeDbJob, fetchUserInfo, useOAuthStore } from 'uiSrc/store'
6+
import { createFreeDbJob, fetchCloudSubscriptionPlans, fetchUserInfo, useOAuthStore } from 'uiSrc/store'
77
import { getApiErrorMessage, parseCustomError, removeInfinityToast, showErrorInfinityToast, showInfinityToast } from 'uiSrc/utils'
88

99
let isFlowInProgress = false
@@ -41,6 +41,8 @@ export const processOauthCallback = ({ status, message = '', error }: CloudAuthR
4141
removeInfinityToast()
4242
},
4343
})
44+
45+
return
4446
}
4547

4648
showInfinityToast(INFINITE_MESSAGES.PENDING_CREATE_DB(CloudJobStep.Credentials).Inner)
@@ -59,7 +61,7 @@ export const processOauthCallback = ({ status, message = '', error }: CloudAuthR
5961
// return
6062
// }
6163

62-
// dispatch(fetchPlans())
64+
fetchCloudSubscriptionPlans()
6365
}
6466

6567
setJob({ id: '', name: CloudJobName.CreateFreeSubscriptionAndDatabase, status: '' })

src/webviews/src/constants/cloud/source.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ export const OAuthProviders = [{
9191
id: OAuthProvider.AWS,
9292
icon: AWSIcon,
9393
label: 'Amazon Web Services',
94-
// className: styles.awsIcon,
9594
}, {
9695
id: OAuthProvider.Google,
9796
icon: GoogleIcon,
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
export const MOCK_NO_TF_REGION = {
2+
id: 12148,
3+
type: 'fixed',
4+
name: 'Cache 30MB',
5+
provider: 'AWS',
6+
price: 0,
7+
region: 'us-east-2',
8+
regionId: 4,
9+
details: {
10+
id: '4',
11+
name: 'us-east-2',
12+
cloud: 'AWS',
13+
displayOrder: 4,
14+
countryName: 'Europe',
15+
cityName: 'Ireland',
16+
regionId: 4,
17+
flag: 'ie',
18+
},
19+
}
20+
21+
export const MOCK_RS_PREVIEW_REGION = {
22+
id: 12148,
23+
type: 'fixed',
24+
name: 'Cache 30MB',
25+
provider: 'AWS',
26+
price: 0,
27+
region: 'us-east-2',
28+
regionId: 1,
29+
details: {
30+
id: '1',
31+
name: 'us-east-2',
32+
cloud: 'AWS',
33+
displayOrder: 1,
34+
countryName: 'US West',
35+
cityName: 'Oregon',
36+
regionId: 1,
37+
flag: 'ie',
38+
},
39+
}
40+
41+
export const MOCK_REGIONS = [
42+
MOCK_NO_TF_REGION,
43+
{
44+
id: 12150,
45+
type: 'fixed',
46+
name: 'Cache 30MB',
47+
provider: 'AWS',
48+
price: 0,
49+
region: 'ap-southeast-1',
50+
regionId: 5,
51+
details: {
52+
id: '5',
53+
name: 'ap-southeast-1',
54+
cloud: 'AWS',
55+
displayOrder: 7,
56+
countryName: 'Asia Pacific',
57+
cityName: 'Singapore',
58+
regionId: 5,
59+
flag: 'sg',
60+
},
61+
},
62+
{
63+
id: 12152,
64+
type: 'fixed',
65+
name: 'Cache 30MB',
66+
provider: 'Azure',
67+
price: 0,
68+
region: 'east-us',
69+
regionId: 16,
70+
details: {
71+
id: '16',
72+
name: 'east-us',
73+
cloud: 'Azure',
74+
displayOrder: 10,
75+
countryName: 'East US',
76+
cityName: 'Virginia',
77+
regionId: 16,
78+
flag: 'us',
79+
},
80+
},
81+
{
82+
id: 12153,
83+
type: 'fixed',
84+
name: 'Cache 30MB',
85+
provider: 'GCP',
86+
price: 0,
87+
region: 'us-central1',
88+
regionId: 27,
89+
details: {
90+
id: '27',
91+
name: 'us-central1',
92+
cloud: 'GCP',
93+
displayOrder: 17,
94+
countryName: 'North America',
95+
cityName: 'Iowa',
96+
regionId: 27,
97+
flag: 'us',
98+
},
99+
},
100+
]
101+
102+
export const MOCK_CUSTOM_REGIONS = [
103+
{
104+
id: 12150,
105+
type: 'fixed',
106+
name: 'Cache 30MB',
107+
provider: 'AWS',
108+
price: 0,
109+
region: 'custom-1',
110+
regionId: 11,
111+
details: {
112+
id: '11',
113+
name: 'custom-1',
114+
cloud: 'AWS',
115+
displayOrder: 2,
116+
countryName: 'Asia Pacific',
117+
cityName: 'Singapore',
118+
regionId: 11,
119+
flag: 'sg',
120+
},
121+
},
122+
{
123+
id: 12152,
124+
type: 'fixed',
125+
name: 'Cache 30MB',
126+
provider: 'Azure',
127+
price: 0,
128+
region: 'custom-2',
129+
regionId: 16,
130+
details: {
131+
id: '16',
132+
name: 'custom-2',
133+
cloud: 'Azure',
134+
displayOrder: 10,
135+
countryName: 'East US',
136+
cityName: 'Virginia',
137+
regionId: 16,
138+
flag: 'us',
139+
},
140+
},
141+
{
142+
id: 12153,
143+
type: 'fixed',
144+
name: 'Cache 30MB',
145+
provider: 'GCP',
146+
price: 0,
147+
region: 'custom-3',
148+
regionId: 27,
149+
details: {
150+
id: '27',
151+
name: 'custom-3',
152+
cloud: 'GCP',
153+
displayOrder: 17,
154+
countryName: 'North America',
155+
cityName: 'Iowa',
156+
regionId: 27,
157+
flag: 'us',
158+
},
159+
},
160+
]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import OAuthSsoDialog from './oauth-sso-dialog'
22
import OAuthJobs from './oauth-jobs'
33
import OAuthCreateFreeDb from './oauth-create-free-db'
4+
import OAuthSelectPlan from './oauth-select-plan'
45

56
export {
67
OAuthCreateFreeDb,
78
OAuthSsoDialog,
89
OAuthJobs,
10+
OAuthSelectPlan,
911
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import React from 'react'
2+
3+
import { Mock } from 'vitest'
4+
import { CloudSubscriptionPlanResponse, OAuthStore } from 'uiSrc/store/hooks/use-oauth/interface'
5+
import { createFreeDbJob, initialOAuthState, useOAuthStore } from 'uiSrc/store'
6+
import * as store from 'uiSrc/store'
7+
import * as utils from 'uiSrc/utils'
8+
import { sendEventTelemetry } from 'uiSrc/utils'
9+
import { MOCK_CUSTOM_REGIONS, MOCK_REGIONS } from 'uiSrc/constants/mocks/mock-sso'
10+
import { fireEvent, render, screen } from 'testSrc/helpers'
11+
import OAuthSelectPlan from './OAuthSelectPlan'
12+
13+
const customState: OAuthStore = {
14+
...initialOAuthState,
15+
plan: {
16+
...initialOAuthState.plan,
17+
isOpenDialog: true,
18+
data: [],
19+
},
20+
}
21+
22+
beforeEach(() => {
23+
useOAuthStore.setState(customState)
24+
})
25+
26+
vi.spyOn(utils, 'sendEventTelemetry')
27+
vi.spyOn(store, 'createFreeDbJob')
28+
29+
describe('OAuthSelectPlan', () => {
30+
beforeEach(() => {
31+
useOAuthStore.setState({
32+
...customState,
33+
plan: {
34+
...customState.plan,
35+
isOpenDialog: true,
36+
data: MOCK_REGIONS as CloudSubscriptionPlanResponse[],
37+
},
38+
})
39+
})
40+
41+
it('should render', () => {
42+
expect(render(<OAuthSelectPlan />)).toBeTruthy()
43+
})
44+
45+
it('should not render if isOpenDialog=false', () => {
46+
useOAuthStore.setState({
47+
...customState,
48+
plan: {
49+
...customState.plan,
50+
isOpenDialog: false,
51+
},
52+
})
53+
54+
const { queryByTestId } = render(<OAuthSelectPlan />)
55+
56+
expect(queryByTestId('oauth-select-plan-dialog')).not.toBeInTheDocument()
57+
})
58+
59+
it('should send telemetry after close modal', () => {
60+
const sendEventTelemetryMock = vi.fn();
61+
(sendEventTelemetry as Mock).mockImplementation(() => sendEventTelemetryMock)
62+
63+
render(<OAuthSelectPlan />)
64+
65+
fireEvent.click(screen.getByTestId('close-icon-oauth-select-plan-dialog'))
66+
67+
expect(sendEventTelemetry).toBeCalledWith({
68+
event: utils.TelemetryEvent.CLOUD_SIGN_IN_PROVIDER_FORM_CLOSED,
69+
})
70+
})
71+
72+
it('should be selected first region by default', () => {
73+
useOAuthStore.setState({
74+
...customState,
75+
plan: {
76+
...customState.plan,
77+
isOpenDialog: true,
78+
data: MOCK_CUSTOM_REGIONS as CloudSubscriptionPlanResponse[],
79+
},
80+
})
81+
82+
const { queryByTestId } = render(<OAuthSelectPlan />)
83+
84+
const selectedElement = queryByTestId('option-custom-1')
85+
86+
expect(selectedElement).toBeInTheDocument()
87+
})
88+
89+
it('should display text if regions is no available on this vendor', () => {
90+
useOAuthStore.setState({
91+
...customState,
92+
plan: {
93+
...customState.plan,
94+
isOpenDialog: true,
95+
data: [],
96+
},
97+
})
98+
99+
const { queryByTestId } = render(<OAuthSelectPlan />)
100+
101+
const selectDescriptionElement = queryByTestId('select-region-select-description')
102+
103+
expect(selectDescriptionElement).toBeInTheDocument()
104+
expect(selectDescriptionElement).toHaveTextContent('No regions available, try another vendor.')
105+
})
106+
107+
it('should initiate database creation', () => {
108+
const createFreeDbJobMock = vi.fn();
109+
(createFreeDbJob as Mock).mockImplementation(() => createFreeDbJobMock)
110+
111+
useOAuthStore.setState({
112+
...customState,
113+
plan: {
114+
...customState.plan,
115+
isOpenDialog: true,
116+
data: MOCK_CUSTOM_REGIONS as CloudSubscriptionPlanResponse[],
117+
loading: false,
118+
},
119+
})
120+
121+
render(<OAuthSelectPlan />)
122+
123+
expect(screen.getByText('Asia Pacific (Singapore)')).toBeInTheDocument()
124+
const submitButton = screen.getByTestId('submit-oauth-select-plan-dialog')
125+
fireEvent.click(submitButton)
126+
expect(createFreeDbJob).toHaveBeenCalledTimes(1)
127+
expect(createFreeDbJob).toHaveBeenCalledWith(
128+
expect.objectContaining({
129+
name: 'CREATE_FREE_SUBSCRIPTION_AND_DATABASE',
130+
resources: { planId: 12150 },
131+
onSuccessAction: expect.any(Function),
132+
}),
133+
)
134+
})
135+
})

0 commit comments

Comments
 (0)