@hashicorp/react-components 0.0.0-nightly.97eb452 → 0.0.0-nightly.9aa5827
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +1 -2
- package/.stylelintrc.js +1 -1
- package/README.md +1 -1
- package/package.json +3 -8
- package/postcss.config.js +1 -1
- package/src/components/nav-panel/components/flight-icon/index.tsx +51 -0
- package/src/components/nav-panel/components/flight-icon/style.module.css +3 -0
- package/src/components/nav-panel/components/link/index.tsx +127 -0
- package/src/components/nav-panel/components/link/style.module.css +64 -0
- package/src/components/nav-panel/components/link-list/index.tsx +13 -65
- package/src/components/nav-panel/components/link-list/style.module.css +1 -50
- package/src/components/nav-panel/components/panel/column/style.module.css +2 -2
- package/src/components/nav-panel/components/panel/root/style.module.css +5 -5
- package/src/components/nav-panel/components/promo/index.tsx +31 -11
- package/src/components/nav-panel/components/promo/style.module.css +26 -12
- package/src/components/nav-panel/components/text/index.tsx +34 -0
- package/src/components/nav-panel/product-panel/index.tsx +54 -17
- package/src/components/nav-panel/product-panel/style.module.css +116 -36
- package/src/components/nav-panel/standard-panel/index.tsx +3 -0
- package/src/components/nav-panel/standard-panel/style.module.css +2 -2
- package/src/lib/get-localized-link-props/index.test.ts +30 -0
- package/src/lib/get-localized-link-props/index.ts +45 -0
- package/src/lib/parse-url/index.test.ts +30 -1
- package/src/lib/parse-url/index.ts +71 -8
- package/src/lib/send-posthog-event/index.ts +22 -0
- package/src/lib/supported-locales/index.ts +10 -0
- package/src/lib/track-nav-click-event/index.ts +4 -4
- package/src/components/actions/index.tsx +0 -107
- package/src/components/actions/style.module.css +0 -28
- package/src/components/actions/types.ts +0 -73
- package/src/components/call-to-action/index.tsx +0 -205
- package/src/components/call-to-action/styles/variant-centered.module.css +0 -93
- package/src/components/call-to-action/styles/variant-compact-grid.module.css +0 -88
- package/src/components/call-to-action/styles/variant-compact.module.css +0 -91
- package/src/components/call-to-action/styles/variant-links.module.css +0 -85
- package/src/components/card/README.md +0 -11
- package/src/components/card/card.tsx +0 -45
- package/src/components/card/index.test.tsx +0 -69
- package/src/components/card/index.tsx +0 -14
- package/src/components/card/newsroom-card/index.test.tsx +0 -39
- package/src/components/card/newsroom-card/index.tsx +0 -37
- package/src/components/card/newsroom-card/style.module.css +0 -12
- package/src/components/card/partner-card/index.test.tsx +0 -57
- package/src/components/card/partner-card/index.tsx +0 -69
- package/src/components/card/partner-card/style.module.css +0 -24
- package/src/components/card/person-card/index.test.tsx +0 -71
- package/src/components/card/person-card/index.tsx +0 -93
- package/src/components/card/person-card/style.module.css +0 -33
- package/src/components/card/primitives.tsx +0 -177
- package/src/components/card/promo-card/index.tsx +0 -51
- package/src/components/card/resource-card/index.test.tsx +0 -48
- package/src/components/card/resource-card/index.tsx +0 -37
- package/src/components/card/style.module.css +0 -145
- package/src/components/card/types.ts +0 -66
- package/src/components/card/unified-card/index.spec.tsx +0 -40
- package/src/components/card/unified-card/index.tsx +0 -58
- package/src/components/intro/index.tsx +0 -82
- package/src/components/intro/style.module.css +0 -67
- package/src/components/intro/types.ts +0 -44
- package/src/components/marketo-form/CHANGELOG.md +0 -122
- package/src/components/marketo-form/README.md +0 -1
- package/src/components/marketo-form/contexts/FormMetadata.ts +0 -13
- package/src/components/marketo-form/docs.mdx +0 -197
- package/src/components/marketo-form/fixtures/index.ts +0 -185
- package/src/components/marketo-form/form/index.tsx +0 -371
- package/src/components/marketo-form/index.test.tsx +0 -320
- package/src/components/marketo-form/index.ts +0 -11
- package/src/components/marketo-form/package.original.json +0 -30
- package/src/components/marketo-form/partials/error-message/index.tsx +0 -12
- package/src/components/marketo-form/partials/error-message/style.module.css +0 -13
- package/src/components/marketo-form/partials/field/index.tsx +0 -90
- package/src/components/marketo-form/partials/field-wrapper/index.tsx +0 -26
- package/src/components/marketo-form/partials/fields/checkbox-field/index.tsx +0 -32
- package/src/components/marketo-form/partials/fields/email-field/index.tsx +0 -35
- package/src/components/marketo-form/partials/fields/form-page-url-field/index.tsx +0 -23
- package/src/components/marketo-form/partials/fields/hidden-field/index.tsx +0 -38
- package/src/components/marketo-form/partials/fields/htmltext-field/index.tsx +0 -21
- package/src/components/marketo-form/partials/fields/htmltext-field/style.module.css +0 -18
- package/src/components/marketo-form/partials/fields/name-field/index.tsx +0 -19
- package/src/components/marketo-form/partials/fields/name-field/style.module.css +0 -13
- package/src/components/marketo-form/partials/fields/radio-buttons-field/index.tsx +0 -48
- package/src/components/marketo-form/partials/fields/select-field/index.tsx +0 -39
- package/src/components/marketo-form/partials/fields/select-field/style.module.css +0 -5
- package/src/components/marketo-form/partials/fields/telephone-field/index.tsx +0 -30
- package/src/components/marketo-form/partials/fields/text-field/index.tsx +0 -30
- package/src/components/marketo-form/partials/fields/textarea-field/index.tsx +0 -29
- package/src/components/marketo-form/partials/label/index.tsx +0 -24
- package/src/components/marketo-form/partials/label/style.module.css +0 -12
- package/src/components/marketo-form/partials/visibility-rule/index.tsx +0 -84
- package/src/components/marketo-form/props.js +0 -66
- package/src/components/marketo-form/server/api-routes.ts +0 -109
- package/src/components/marketo-form/server/client.ts +0 -98
- package/src/components/marketo-form/server/index.ts +0 -8
- package/src/components/marketo-form/types.ts +0 -268
- package/src/components/marketo-form/utils.test.tsx +0 -103
- package/src/components/marketo-form/utils.ts +0 -449
- package/src/components/next-steps/index.tsx +0 -138
- package/src/components/next-steps/style.module.css +0 -270
- package/src/components/next-steps/types.ts +0 -63
- package/src/components/product-badge/index.test.tsx +0 -11
- package/src/components/product-badge/index.tsx +0 -42
- package/src/components/product-badge/style.module.css +0 -76
- package/src/components/products-used/index.tsx +0 -84
- package/src/components/products-used/style.module.css +0 -87
- package/src/components/products-used/types.ts +0 -31
- package/src/components/related-content/index.test.tsx +0 -74
- package/src/components/related-content/index.tsx +0 -56
- package/src/components/related-content/style.module.css +0 -89
- package/src/components/related-content/types.ts +0 -21
- package/src/components/subnav/helpers/areBasePathsMatching.ts +0 -13
- package/src/components/subnav/helpers/traverse/index.ts +0 -42
- package/src/components/subnav/helpers/useHeightRef.ts +0 -42
- package/src/components/subnav/helpers/useNavRef.ts +0 -30
- package/src/components/subnav/helpers/useOverflowRef.ts +0 -85
- package/src/components/subnav/helpers/useStuckRef.ts +0 -51
- package/src/components/subnav/index.tsx +0 -203
- package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.test.ts +0 -26
- package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.ts +0 -22
- package/src/components/subnav/partials/CtaLinks/github-stars-link/index.tsx +0 -87
- package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.test.ts +0 -29
- package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.ts +0 -32
- package/src/components/subnav/partials/CtaLinks/github-stars-link/style.module.css +0 -81
- package/src/components/subnav/partials/CtaLinks/icons/github-logo.js +0 -20
- package/src/components/subnav/partials/CtaLinks/icons/github.svg.js +0 -7
- package/src/components/subnav/partials/CtaLinks/icons/star.js +0 -20
- package/src/components/subnav/partials/CtaLinks/index.tsx +0 -131
- package/src/components/subnav/partials/CtaLinks/style.module.css +0 -45
- package/src/components/subnav/partials/DropdownTrigger/index.tsx +0 -35
- package/src/components/subnav/partials/DropdownTrigger/style.module.css +0 -39
- package/src/components/subnav/partials/MenuItemsDefault/index.tsx +0 -158
- package/src/components/subnav/partials/MenuItemsDefault/style.module.css +0 -104
- package/src/components/subnav/partials/MenuItemsOverflow/index.tsx +0 -143
- package/src/components/subnav/partials/MenuItemsOverflow/style.module.css +0 -88
- package/src/components/subnav/partials/TitleLink/index.tsx +0 -113
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-dark.ts +0 -10
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-light.ts +0 -10
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-dark.ts +0 -23
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-light.ts +0 -23
- package/src/components/subnav/partials/TitleLink/style.module.css +0 -43
- package/src/components/subnav/partials/nav-item-text/index.tsx +0 -37
- package/src/components/subnav/partials/nav-item-text/style.module.css +0 -13
- package/src/components/subnav/style.module.css +0 -66
- package/src/components/subnav/subnav-consts.ts +0 -1
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import { render, screen, waitFor } from '@testing-library/react'
|
|
2
|
-
import nock from 'nock'
|
|
3
|
-
import userEvent from '@testing-library/user-event'
|
|
4
|
-
import MarketoForm from './'
|
|
5
|
-
import {
|
|
6
|
-
BASIC_FORM_PROPS,
|
|
7
|
-
UTM_FORM_PROPS,
|
|
8
|
-
VISIBILITY_RULE_FORM_PROPS,
|
|
9
|
-
COOKIE_UTM_FORM_PROPS,
|
|
10
|
-
HIDDEN_COOKIE_FIELD_FORM_PROPS,
|
|
11
|
-
} from './fixtures'
|
|
12
|
-
import cookie from 'js-cookie'
|
|
13
|
-
|
|
14
|
-
describe('MarketoForm', () => {
|
|
15
|
-
let originalLocation
|
|
16
|
-
let spy
|
|
17
|
-
|
|
18
|
-
beforeAll(() => {
|
|
19
|
-
originalLocation = window.location
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
nock('http://local.test')
|
|
24
|
-
.persist()
|
|
25
|
-
.post('/api/marketo/submit')
|
|
26
|
-
.reply(200, { success: true, result: [] })
|
|
27
|
-
|
|
28
|
-
delete window.location
|
|
29
|
-
window.location = {
|
|
30
|
-
// We use an absolute URL here since fetch in Jest can't use relative URLs
|
|
31
|
-
origin: 'http://local.test',
|
|
32
|
-
protocol: 'http:',
|
|
33
|
-
host: 'local.test',
|
|
34
|
-
pathname: '/testing',
|
|
35
|
-
href: 'http://local.test/testing?utm_medium=social',
|
|
36
|
-
search: '?utm_medium=social',
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
spy = vi.spyOn(global, 'fetch')
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
afterEach(() => {
|
|
43
|
-
vi.resetAllMocks()
|
|
44
|
-
spy.mockRestore()
|
|
45
|
-
window.location = originalLocation
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
afterAll(() => {
|
|
49
|
-
nock.restore()
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
test('renders form with provided fields', async () => {
|
|
53
|
-
render(<MarketoForm {...BASIC_FORM_PROPS} />)
|
|
54
|
-
|
|
55
|
-
const firstNameField = screen.getByLabelText(/First Name/)
|
|
56
|
-
const lastNameField = screen.getByLabelText(/Last Name/)
|
|
57
|
-
expect(firstNameField).toBeInTheDocument()
|
|
58
|
-
expect(lastNameField).toBeInTheDocument()
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test('submits form data', async () => {
|
|
62
|
-
render(<MarketoForm {...BASIC_FORM_PROPS} />)
|
|
63
|
-
|
|
64
|
-
const firstNameField = screen.getByLabelText(/First Name/)
|
|
65
|
-
expect(firstNameField).toBeInTheDocument()
|
|
66
|
-
userEvent.type(firstNameField, 'Michael')
|
|
67
|
-
|
|
68
|
-
const lastNameField = screen.getByLabelText(/Last Name/)
|
|
69
|
-
expect(lastNameField).toBeInTheDocument()
|
|
70
|
-
userEvent.type(lastNameField, 'Burnham')
|
|
71
|
-
|
|
72
|
-
const submitButton = screen.getByText('Submit')
|
|
73
|
-
expect(submitButton).toBeInTheDocument()
|
|
74
|
-
userEvent.click(submitButton)
|
|
75
|
-
|
|
76
|
-
await waitFor(() => expect(spy).toHaveBeenCalled())
|
|
77
|
-
expect(spy).toHaveBeenCalledWith('http://local.test/api/marketo/submit', {
|
|
78
|
-
method: 'POST',
|
|
79
|
-
headers: {
|
|
80
|
-
'Content-Type': 'application/json',
|
|
81
|
-
},
|
|
82
|
-
body: JSON.stringify({
|
|
83
|
-
input: [
|
|
84
|
-
{
|
|
85
|
-
leadFormFields: {
|
|
86
|
-
firstName: 'Michael',
|
|
87
|
-
lastName: 'Burnham',
|
|
88
|
-
},
|
|
89
|
-
visitorData: {
|
|
90
|
-
pageURL: 'http://local.test/testing?utm_medium=social',
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
],
|
|
94
|
-
formId: 9999,
|
|
95
|
-
}),
|
|
96
|
-
})
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
test('submits with initial values', async () => {
|
|
100
|
-
render(
|
|
101
|
-
<MarketoForm
|
|
102
|
-
{...BASIC_FORM_PROPS}
|
|
103
|
-
initialValues={{ LastName: 'Burnham' }}
|
|
104
|
-
/>
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
const firstNameField = screen.getByLabelText(/First Name/)
|
|
108
|
-
expect(firstNameField).toBeInTheDocument()
|
|
109
|
-
userEvent.type(firstNameField, 'Michael')
|
|
110
|
-
|
|
111
|
-
const submitButton = screen.getByText('Submit')
|
|
112
|
-
expect(submitButton).toBeInTheDocument()
|
|
113
|
-
userEvent.click(submitButton)
|
|
114
|
-
|
|
115
|
-
await waitFor(() => expect(spy).toHaveBeenCalled())
|
|
116
|
-
expect(spy).toHaveBeenCalledWith('http://local.test/api/marketo/submit', {
|
|
117
|
-
method: 'POST',
|
|
118
|
-
headers: {
|
|
119
|
-
'Content-Type': 'application/json',
|
|
120
|
-
},
|
|
121
|
-
body: JSON.stringify({
|
|
122
|
-
input: [
|
|
123
|
-
{
|
|
124
|
-
leadFormFields: {
|
|
125
|
-
firstName: 'Michael',
|
|
126
|
-
lastName: 'Burnham',
|
|
127
|
-
},
|
|
128
|
-
visitorData: {
|
|
129
|
-
pageURL: 'http://local.test/testing?utm_medium=social',
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
],
|
|
133
|
-
formId: 9999,
|
|
134
|
-
}),
|
|
135
|
-
})
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
test('submits form data with UTM params', async () => {
|
|
139
|
-
render(<MarketoForm {...UTM_FORM_PROPS} />)
|
|
140
|
-
|
|
141
|
-
const firstNameField = screen.getByLabelText(/First Name/)
|
|
142
|
-
expect(firstNameField).toBeInTheDocument()
|
|
143
|
-
userEvent.type(firstNameField, 'Michael')
|
|
144
|
-
|
|
145
|
-
const lastNameField = screen.getByLabelText(/Last Name/)
|
|
146
|
-
expect(lastNameField).toBeInTheDocument()
|
|
147
|
-
userEvent.type(lastNameField, 'Burnham')
|
|
148
|
-
|
|
149
|
-
const submitButton = screen.getByText('Submit')
|
|
150
|
-
expect(submitButton).toBeInTheDocument()
|
|
151
|
-
userEvent.click(submitButton)
|
|
152
|
-
|
|
153
|
-
await waitFor(() => expect(spy).toHaveBeenCalled())
|
|
154
|
-
expect(spy).toHaveBeenCalledWith('http://local.test/api/marketo/submit', {
|
|
155
|
-
method: 'POST',
|
|
156
|
-
headers: {
|
|
157
|
-
'Content-Type': 'application/json',
|
|
158
|
-
},
|
|
159
|
-
body: JSON.stringify({
|
|
160
|
-
input: [
|
|
161
|
-
{
|
|
162
|
-
leadFormFields: {
|
|
163
|
-
firstName: 'Michael',
|
|
164
|
-
lastName: 'Burnham',
|
|
165
|
-
utm_medium__c: 'social',
|
|
166
|
-
form_page_url__c: 'http://local.test/testing',
|
|
167
|
-
},
|
|
168
|
-
visitorData: {
|
|
169
|
-
pageURL: 'http://local.test/testing?utm_medium=social',
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
],
|
|
173
|
-
formId: 9999,
|
|
174
|
-
}),
|
|
175
|
-
})
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
test('submits form data with UTM params from cookies', async () => {
|
|
179
|
-
cookie.get = vi.fn().mockImplementation(() => {
|
|
180
|
-
return { utm_content: 'utm-content-cookie-val' }
|
|
181
|
-
})
|
|
182
|
-
render(<MarketoForm {...COOKIE_UTM_FORM_PROPS} />)
|
|
183
|
-
|
|
184
|
-
const firstNameField = screen.getByLabelText(/First Name/)
|
|
185
|
-
expect(firstNameField).toBeInTheDocument()
|
|
186
|
-
userEvent.type(firstNameField, 'Michael')
|
|
187
|
-
|
|
188
|
-
const lastNameField = screen.getByLabelText(/Last Name/)
|
|
189
|
-
expect(lastNameField).toBeInTheDocument()
|
|
190
|
-
userEvent.type(lastNameField, 'Burnham')
|
|
191
|
-
|
|
192
|
-
const submitButton = screen.getByText('Submit')
|
|
193
|
-
expect(submitButton).toBeInTheDocument()
|
|
194
|
-
userEvent.click(submitButton)
|
|
195
|
-
|
|
196
|
-
await waitFor(() => expect(spy).toHaveBeenCalled())
|
|
197
|
-
expect(spy).toHaveBeenCalledWith('http://local.test/api/marketo/submit', {
|
|
198
|
-
method: 'POST',
|
|
199
|
-
headers: {
|
|
200
|
-
'Content-Type': 'application/json',
|
|
201
|
-
},
|
|
202
|
-
body: JSON.stringify({
|
|
203
|
-
input: [
|
|
204
|
-
{
|
|
205
|
-
leadFormFields: {
|
|
206
|
-
firstName: 'Michael',
|
|
207
|
-
lastName: 'Burnham',
|
|
208
|
-
utm_content__c: 'utm-content-cookie-val',
|
|
209
|
-
},
|
|
210
|
-
visitorData: {
|
|
211
|
-
pageURL: 'http://local.test/testing?utm_medium=social',
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
],
|
|
215
|
-
formId: 9999,
|
|
216
|
-
}),
|
|
217
|
-
})
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
test('renders built-in error validation messages', async () => {
|
|
221
|
-
render(<MarketoForm {...BASIC_FORM_PROPS} />)
|
|
222
|
-
|
|
223
|
-
const firstNameField = screen.getByLabelText(/First Name/)
|
|
224
|
-
expect(firstNameField).toBeInTheDocument()
|
|
225
|
-
userEvent.click(firstNameField)
|
|
226
|
-
|
|
227
|
-
const lastNameField = screen.getByLabelText(/Last Name/)
|
|
228
|
-
expect(lastNameField).toBeInTheDocument()
|
|
229
|
-
userEvent.click(lastNameField)
|
|
230
|
-
|
|
231
|
-
const errorMessage = await screen.findByText('This field is required.')
|
|
232
|
-
expect(errorMessage).toBeInTheDocument()
|
|
233
|
-
})
|
|
234
|
-
|
|
235
|
-
test('renders additional error validation messages', async () => {
|
|
236
|
-
render(
|
|
237
|
-
<MarketoForm
|
|
238
|
-
{...BASIC_FORM_PROPS}
|
|
239
|
-
validateFields={async (values, errors) => {
|
|
240
|
-
return {
|
|
241
|
-
values,
|
|
242
|
-
errors: {
|
|
243
|
-
...errors,
|
|
244
|
-
FirstName: {
|
|
245
|
-
message: `${errors.FirstName.message} Additional message.`,
|
|
246
|
-
},
|
|
247
|
-
},
|
|
248
|
-
}
|
|
249
|
-
}}
|
|
250
|
-
/>
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
const firstNameField = screen.getByLabelText(/First Name/)
|
|
254
|
-
expect(firstNameField).toBeInTheDocument()
|
|
255
|
-
userEvent.click(firstNameField)
|
|
256
|
-
|
|
257
|
-
const lastNameField = screen.getByLabelText(/Last Name/)
|
|
258
|
-
expect(lastNameField).toBeInTheDocument()
|
|
259
|
-
userEvent.click(lastNameField)
|
|
260
|
-
|
|
261
|
-
const errorMessage = await screen.findByText(
|
|
262
|
-
'This field is required. Additional message.'
|
|
263
|
-
)
|
|
264
|
-
expect(errorMessage).toBeInTheDocument()
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
test('handles simple visibility rules', async () => {
|
|
268
|
-
render(<MarketoForm {...VISIBILITY_RULE_FORM_PROPS} />)
|
|
269
|
-
|
|
270
|
-
expect(screen.queryByLabelText('Phone Number')).toBeNull()
|
|
271
|
-
|
|
272
|
-
const fastTrackField = screen.getByLabelText('Have salesperson contact me')
|
|
273
|
-
expect(fastTrackField).toBeInTheDocument()
|
|
274
|
-
userEvent.click(fastTrackField)
|
|
275
|
-
|
|
276
|
-
expect(screen.getByLabelText('Phone Number')).toBeInTheDocument()
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
test('submits form with cookie values for hidden fields', async () => {
|
|
280
|
-
cookie.get = vi.fn().mockImplementation(() => {
|
|
281
|
-
return 'hidden-cookie-field-val'
|
|
282
|
-
})
|
|
283
|
-
render(<MarketoForm {...HIDDEN_COOKIE_FIELD_FORM_PROPS} />)
|
|
284
|
-
|
|
285
|
-
const firstNameField = screen.getByLabelText(/First Name/)
|
|
286
|
-
expect(firstNameField).toBeInTheDocument()
|
|
287
|
-
userEvent.type(firstNameField, 'Michael')
|
|
288
|
-
|
|
289
|
-
const lastNameField = screen.getByLabelText(/Last Name/)
|
|
290
|
-
expect(lastNameField).toBeInTheDocument()
|
|
291
|
-
userEvent.type(lastNameField, 'Burnham')
|
|
292
|
-
|
|
293
|
-
const submitButton = screen.getByText('Submit')
|
|
294
|
-
expect(submitButton).toBeInTheDocument()
|
|
295
|
-
userEvent.click(submitButton)
|
|
296
|
-
|
|
297
|
-
await waitFor(() => expect(spy).toHaveBeenCalled())
|
|
298
|
-
expect(spy).toHaveBeenCalledWith('http://local.test/api/marketo/submit', {
|
|
299
|
-
method: 'POST',
|
|
300
|
-
headers: {
|
|
301
|
-
'Content-Type': 'application/json',
|
|
302
|
-
},
|
|
303
|
-
body: JSON.stringify({
|
|
304
|
-
input: [
|
|
305
|
-
{
|
|
306
|
-
leadFormFields: {
|
|
307
|
-
firstName: 'Michael',
|
|
308
|
-
lastName: 'Burnham',
|
|
309
|
-
cookieHiddenField: 'hidden-cookie-field-val',
|
|
310
|
-
},
|
|
311
|
-
visitorData: {
|
|
312
|
-
pageURL: 'http://local.test/testing?utm_medium=social',
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
],
|
|
316
|
-
formId: 9999,
|
|
317
|
-
}),
|
|
318
|
-
})
|
|
319
|
-
})
|
|
320
|
-
})
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useFormContext, useFormState, useWatch } from 'react-hook-form'
|
|
7
|
-
import Form, { defaultFieldGroupings } from './form'
|
|
8
|
-
import Field from './partials/field'
|
|
9
|
-
|
|
10
|
-
export { useFormContext, useFormState, useWatch, defaultFieldGroupings, Field }
|
|
11
|
-
export default Form
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@hashicorp/react-marketo-form",
|
|
3
|
-
"description": "A form component that dynamically renders a Marketo form",
|
|
4
|
-
"version": "0.9.0",
|
|
5
|
-
"author": "HashiCorp",
|
|
6
|
-
"contributors": [
|
|
7
|
-
"Dylan Staley"
|
|
8
|
-
],
|
|
9
|
-
"dependencies": {
|
|
10
|
-
"@hashicorp/platform-analytics": "^0.11.2",
|
|
11
|
-
"@hashicorp/react-button": "^6.2.0",
|
|
12
|
-
"@hashicorp/react-form-fields": "^0.2.0",
|
|
13
|
-
"@vercel/fetch": "^6.2.0",
|
|
14
|
-
"clsx": "^1.1.1",
|
|
15
|
-
"js-cookie": "^3.0.1",
|
|
16
|
-
"moize": "^6.1.3",
|
|
17
|
-
"react-hook-form": "^7.37.0"
|
|
18
|
-
},
|
|
19
|
-
"license": "MPL-2.0",
|
|
20
|
-
"peerDependencies": {
|
|
21
|
-
"next": ">=11.x",
|
|
22
|
-
"react": ">=16.x"
|
|
23
|
-
},
|
|
24
|
-
"publishConfig": {
|
|
25
|
-
"access": "public"
|
|
26
|
-
},
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@types/js-cookie": "^3.0.2"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import styles from './style.module.css'
|
|
7
|
-
|
|
8
|
-
const ErrorMessage = ({ error }: { error: string }) => {
|
|
9
|
-
return <div className={styles.errorText}>{error}</div>
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default ErrorMessage
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
.errorText {
|
|
7
|
-
--error-text-color: var(--danger);
|
|
8
|
-
|
|
9
|
-
composes: g-type-body-small from global;
|
|
10
|
-
color: var(--error-text-color);
|
|
11
|
-
line-height: 1.4;
|
|
12
|
-
margin-top: 4px;
|
|
13
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import TextField from '../fields/text-field'
|
|
7
|
-
import EmailField from '../fields/email-field'
|
|
8
|
-
import TelephoneField from '../fields/telephone-field'
|
|
9
|
-
import TextareaField from '../fields/textarea-field'
|
|
10
|
-
import SelectField from '../fields/select-field'
|
|
11
|
-
import CheckboxField from '../fields/checkbox-field'
|
|
12
|
-
import HiddenField from '../fields/hidden-field'
|
|
13
|
-
import HtmltextField from '../fields/htmltext-field'
|
|
14
|
-
import RadioButtonsField from '../fields/radio-buttons-field'
|
|
15
|
-
import FormPageUrlField from '../fields/form-page-url-field'
|
|
16
|
-
import type { MarketoFormField, MarketoFormComponents } from '../../types'
|
|
17
|
-
|
|
18
|
-
const Field = ({
|
|
19
|
-
field,
|
|
20
|
-
components,
|
|
21
|
-
}: {
|
|
22
|
-
field: MarketoFormField
|
|
23
|
-
components?: MarketoFormComponents
|
|
24
|
-
}) => {
|
|
25
|
-
switch (field.dataType) {
|
|
26
|
-
case 'text':
|
|
27
|
-
if (components && 'text' in components) {
|
|
28
|
-
const Component = components.text!
|
|
29
|
-
return <Component field={field} />
|
|
30
|
-
}
|
|
31
|
-
return <TextField field={field} />
|
|
32
|
-
case 'textArea':
|
|
33
|
-
if (components && 'textArea' in components) {
|
|
34
|
-
const Component = components.textArea!
|
|
35
|
-
return <Component field={field} />
|
|
36
|
-
}
|
|
37
|
-
return <TextareaField field={field} />
|
|
38
|
-
case 'email':
|
|
39
|
-
if (components && 'email' in components) {
|
|
40
|
-
const Component = components.email!
|
|
41
|
-
return <Component field={field} />
|
|
42
|
-
}
|
|
43
|
-
return <EmailField field={field} />
|
|
44
|
-
case 'telephone':
|
|
45
|
-
if (components && 'telephone' in components) {
|
|
46
|
-
const Component = components.telephone!
|
|
47
|
-
return <Component field={field} />
|
|
48
|
-
}
|
|
49
|
-
return <TelephoneField field={field} />
|
|
50
|
-
case 'select':
|
|
51
|
-
if (components && 'select' in components) {
|
|
52
|
-
const Component = components.select!
|
|
53
|
-
return <Component field={field} />
|
|
54
|
-
}
|
|
55
|
-
return <SelectField field={field} />
|
|
56
|
-
case 'checkbox':
|
|
57
|
-
if (components && 'checkbox' in components) {
|
|
58
|
-
const Component = components.checkbox!
|
|
59
|
-
return <Component field={field} />
|
|
60
|
-
}
|
|
61
|
-
return <CheckboxField field={field} />
|
|
62
|
-
case 'hidden':
|
|
63
|
-
if (components && 'hidden' in components) {
|
|
64
|
-
const Component = components.hidden!
|
|
65
|
-
return <Component field={field} />
|
|
66
|
-
}
|
|
67
|
-
if (field.id === 'form_page_url__c') {
|
|
68
|
-
return <FormPageUrlField field={field} />
|
|
69
|
-
}
|
|
70
|
-
return <HiddenField field={field} />
|
|
71
|
-
case 'htmltext':
|
|
72
|
-
if (components && 'htmltext' in components) {
|
|
73
|
-
const Component = components.htmltext!
|
|
74
|
-
return <Component field={field} />
|
|
75
|
-
}
|
|
76
|
-
return <HtmltextField field={field} />
|
|
77
|
-
case 'radioButtons':
|
|
78
|
-
if (components && 'radioButtons' in components) {
|
|
79
|
-
const Component = components.radioButtons!
|
|
80
|
-
return <Component field={field} />
|
|
81
|
-
}
|
|
82
|
-
return <RadioButtonsField field={field} />
|
|
83
|
-
default:
|
|
84
|
-
console.error(`Unknown form field type: ${(field as any).Datatype}`)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return null
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export default Field
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { ReactNode } from 'react'
|
|
7
|
-
|
|
8
|
-
const FieldWrapper = ({
|
|
9
|
-
children,
|
|
10
|
-
fieldId,
|
|
11
|
-
}: {
|
|
12
|
-
children: ReactNode
|
|
13
|
-
fieldId: string
|
|
14
|
-
}) => {
|
|
15
|
-
return (
|
|
16
|
-
<div
|
|
17
|
-
style={{ marginBottom: '1rem' }}
|
|
18
|
-
className="marketo-form-field-wrapper"
|
|
19
|
-
data-field-id={fieldId}
|
|
20
|
-
>
|
|
21
|
-
{children}
|
|
22
|
-
</div>
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default FieldWrapper
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useFormContext } from 'react-hook-form'
|
|
7
|
-
// import CheckboxInput from '@hashicorp/react-form-fields/checkbox'
|
|
8
|
-
import Checkbox from '@hashicorp/react-hds/src/components/form/checkbox'
|
|
9
|
-
import FieldWrapper from '../../field-wrapper'
|
|
10
|
-
import { formattedLabel, useErrorMessage } from '../../../utils'
|
|
11
|
-
import type { MarketoFormCheckboxField } from '../../../types'
|
|
12
|
-
|
|
13
|
-
const CheckboxField = ({ field }: { field: MarketoFormCheckboxField }) => {
|
|
14
|
-
const { register, watch } = useFormContext()
|
|
15
|
-
const error = useErrorMessage(field.id)
|
|
16
|
-
const checked = watch(field.id, false)
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<FieldWrapper fieldId={field.id}>
|
|
20
|
-
<Checkbox
|
|
21
|
-
label={formattedLabel(field)}
|
|
22
|
-
field={{
|
|
23
|
-
...register(field.id),
|
|
24
|
-
checked,
|
|
25
|
-
}}
|
|
26
|
-
error={error}
|
|
27
|
-
/>
|
|
28
|
-
</FieldWrapper>
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export default CheckboxField
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useFormContext } from 'react-hook-form'
|
|
7
|
-
// import TextInput from '@hashicorp/react-form-fields/text'
|
|
8
|
-
import TextInput from '@hashicorp/react-hds/src/components/form/text-input'
|
|
9
|
-
import FieldWrapper from '../../field-wrapper'
|
|
10
|
-
import { formattedLabel, useErrorMessage } from '../../../utils'
|
|
11
|
-
import type { MarketoFormEmailField } from '../../../types'
|
|
12
|
-
|
|
13
|
-
const EmailField = ({ field }: { field: MarketoFormEmailField }) => {
|
|
14
|
-
const { register } = useFormContext()
|
|
15
|
-
const error = useErrorMessage(field.id)
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<FieldWrapper fieldId={field.id}>
|
|
19
|
-
<TextInput
|
|
20
|
-
label={formattedLabel(field)}
|
|
21
|
-
type="email"
|
|
22
|
-
field={{
|
|
23
|
-
...register(field.id),
|
|
24
|
-
type: 'email',
|
|
25
|
-
placeholder: field.hintText,
|
|
26
|
-
}}
|
|
27
|
-
size="large"
|
|
28
|
-
error={error}
|
|
29
|
-
isRequired={field.required}
|
|
30
|
-
/>
|
|
31
|
-
</FieldWrapper>
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export default EmailField
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use client'
|
|
7
|
-
|
|
8
|
-
import { useEffect } from 'react'
|
|
9
|
-
import { useFormContext } from 'react-hook-form'
|
|
10
|
-
import type { MarketoFormHiddenField } from '../../../types'
|
|
11
|
-
|
|
12
|
-
const FormPageUrlField = ({ field }: { field: MarketoFormHiddenField }) => {
|
|
13
|
-
const { register, setValue } = useFormContext()
|
|
14
|
-
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
const { protocol, host, pathname } = window.location
|
|
17
|
-
setValue(field.id, `${protocol}//${host}${pathname}`)
|
|
18
|
-
}, [])
|
|
19
|
-
|
|
20
|
-
return <input type="hidden" {...register(field.id)} />
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export default FormPageUrlField
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
'use client'
|
|
6
|
-
|
|
7
|
-
import { useEffect } from 'react'
|
|
8
|
-
import { useFormContext } from 'react-hook-form'
|
|
9
|
-
import type { MarketoFormHiddenField } from '../../../types'
|
|
10
|
-
import cookies from 'js-cookie'
|
|
11
|
-
|
|
12
|
-
const HiddenField = ({ field }: { field: MarketoFormHiddenField }) => {
|
|
13
|
-
const { register, setValue } = useFormContext()
|
|
14
|
-
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
if (field.autoFill && field.autoFill.valueFrom === 'query') {
|
|
17
|
-
const searchParams = new URLSearchParams(window.location.search)
|
|
18
|
-
if (searchParams.has(field.autoFill.parameterName)) {
|
|
19
|
-
setValue(field.id, searchParams.get(field.autoFill.parameterName))
|
|
20
|
-
}
|
|
21
|
-
} else if (
|
|
22
|
-
field.autoFill &&
|
|
23
|
-
field.autoFill.valueFrom === 'default' &&
|
|
24
|
-
field.autoFill.value
|
|
25
|
-
) {
|
|
26
|
-
setValue(field.id, field.autoFill.value)
|
|
27
|
-
} else if (field.autoFill && field.autoFill.valueFrom === 'cookie') {
|
|
28
|
-
const fieldCookieValue = cookies.get(field.autoFill.parameterName)
|
|
29
|
-
if (fieldCookieValue) {
|
|
30
|
-
setValue(field.id, fieldCookieValue)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}, [field, setValue])
|
|
34
|
-
|
|
35
|
-
return <input type="hidden" {...register(field.id)} />
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export default HiddenField
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import FieldWrapper from '../../field-wrapper'
|
|
7
|
-
import type { MarketoFormHtmltextField } from '../../../types'
|
|
8
|
-
import styles from './style.module.css'
|
|
9
|
-
|
|
10
|
-
const Index = ({ field }: { field: MarketoFormHtmltextField }) => {
|
|
11
|
-
return (
|
|
12
|
-
<FieldWrapper fieldId={field.id}>
|
|
13
|
-
<span
|
|
14
|
-
className={styles.htmltext}
|
|
15
|
-
dangerouslySetInnerHTML={{ __html: field.text }}
|
|
16
|
-
/>
|
|
17
|
-
</FieldWrapper>
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default Index
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
.htmltext {
|
|
2
|
-
composes: g-type-body-small from global;
|
|
3
|
-
margin-top: var(--hdsplus-spacing-04);
|
|
4
|
-
margin-bottom: var(--hdsplus-spacing-07);
|
|
5
|
-
color: var(--token-color-foreground-faint);
|
|
6
|
-
|
|
7
|
-
& a {
|
|
8
|
-
color: var(--token-color-foreground-action);
|
|
9
|
-
text-decoration: underline;
|
|
10
|
-
|
|
11
|
-
&:focus-visible {
|
|
12
|
-
text-decoration: none;
|
|
13
|
-
border-radius: 2px;
|
|
14
|
-
outline: 2px solid var(--token-color-focus-action-internal);
|
|
15
|
-
outline-offset: 1px;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|