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
4 changes: 3 additions & 1 deletion .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ steps:
- echo "--- Install dependencies"
- yarn install --immutable
- echo "+++ Run Browser integration tests :pray:"
- yarn turbo run --filter=@internal/browser-integration-tests test
- yarn turbo run --filter=@internal/browser-integration-tests test:int
retry:
automatic:
- exit_status: '*'
Expand Down Expand Up @@ -156,6 +156,8 @@ steps:
- yarn turbo run --filter='./packages/signals/*' lint
- echo "+++ Run Tests"
- yarn turbo run --filter='./packages/signals/*' test
- echo "+++ Run Integration Tests"
- yarn turbo run --filter='./packages/signals/*' test:int
plugins:
- ssh://[email protected]/segmentio/cache-buildkite-plugin#v2.0.0:
key: "v1.1-cache-dev-{{ checksum 'yarn.lock' }}"
Expand Down
5 changes: 5 additions & 0 deletions .changeset/slimy-rabbits-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@segment/analytics-signals': patch
---

Fix circular submit error for react-hook-form
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"build": "turbo run build --filter='./packages/**'",
"watch": "turbo run watch --filter='./packages/**'",
"dev": "yarn workspace @playground/next-playground run dev",
"prepush": "yarn lint && CI=true yarn test --colors --silent",
"prepush": "turbo run lint --filter='...[master...HEAD]' && CI=true yarn turbo run test --filter='...[master...HEAD]' -- --colors --silent",
"postinstall": "husky install",
"changeset": "changeset",
"update-versions-and-changelogs": "changeset version && yarn version-run-all && bash scripts/update-lockfile.sh",
Expand Down
2 changes: 1 addition & 1 deletion packages/browser-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"hoistingLimits": "workspaces"
},
"scripts": {
"test": "playwright test",
"test:int": "playwright test",
"lint": "yarn concurrently 'yarn:eslint .' 'yarn:tsc --noEmit'",
"concurrently": "yarn run -T concurrently",
"watch:test": "yarn test --watch",
Expand Down
1 change: 1 addition & 0 deletions packages/signals/signals-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"@segment/analytics-signals": "workspace:^",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-hook-form": "^7.54.2",
"react-router-dom": "^6.23.1"
},
"devDependencies": {
Expand Down
3 changes: 3 additions & 0 deletions packages/signals/signals-example/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { loadAnalytics } from '../lib/analytics'
import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-dom'
import { HomePage } from '../pages/Home'
import { OtherPage } from '../pages/Other'
import { ReactHookFormPage } from '../pages/ReactHookForm'

const App: React.FC = () => {
useEffect(() => {
Expand All @@ -14,11 +15,13 @@ const App: React.FC = () => {
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/reacthookform">React Hook Form Example</Link>
<Link to="/other">Other</Link>
</nav>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/other" element={<OtherPage />} />
<Route path="/reacthookform" element={<ReactHookFormPage />} />
</Routes>
</Router>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from 'react'
import { useForm, SubmitHandler } from 'react-hook-form'

interface IFormInput {
name: string
selectField: string
expectFormError: boolean
}

const ComplexFormWithHookForm = () => {
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm<IFormInput>()
const onSubmit: SubmitHandler<IFormInput> = (data) => {
const statusCode = data.expectFormError ? parseInt(data.name, 10) : 200
const formData = {
status: statusCode,
name: data.name,
selectField: data.selectField,
}
console.log('Submitting form:', JSON.stringify(formData))
fetch('/parrot', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
})
.then((response) => response.json())
.then((data) => {
console.log('Form submitted successfully:', data)
})
.catch((error) => {
console.error('Error submitting form:', error)
})
}

const name = watch('name')
const statusCode = React.useMemo(() => {
try {
const val = parseInt(name, 10)
return val >= 100 && val <= 511 ? val : 400
} catch (err) {
return 400
}
}, [name])

return (
<div>
<button data-custom-attr="some-custom-attribute">Example Button</button>
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="ex-input-text">Input some text:</label>
<input
id="ex-input-text"
type="text"
{...register('name', { required: true })}
/>
{errors.name && <span>This field is required</span>}
</div>
<div>
<label htmlFor="ex-select">Select an option:</label>
<select
id="ex-select"
{...register('selectField', { required: true })}
>
<option value="" disabled>
Select
</option>
<option value="Option 1">Option 1</option>
<option value="Option 2">Option 2</option>
</select>
{errors.selectField && <span>This field is required</span>}
</div>
<div>
<label htmlFor="ex-checkbox">{`Force submit network status: ${statusCode}`}</label>
<input
id="ex-checkbox"
type="checkbox"
{...register('expectFormError')}
/>
</div>
<button type="submit">Submit via network req</button>
</form>
<button>
<div>
Other Example Button with <h1>Nested Text</h1>
</div>
</button>
</div>
)
}

export default ComplexFormWithHookForm
15 changes: 15 additions & 0 deletions packages/signals/signals-example/src/pages/ReactHookForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import ComplexForm from '../components/ComplexReactHookForm'
import { analytics } from '../lib/analytics'

export const ReactHookFormPage: React.FC = () => {
return (
<main>
<h1>Hello, React Hook Form with TypeScript!</h1>
<ComplexForm />
<button onClick={() => analytics.track('manual track call')}>
Send Manual Track Call
</button>
</main>
)
}
2 changes: 1 addition & 1 deletion packages/signals/signals-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"scripts": {
".": "yarn run -T turbo run --filter=@internal/signals-integration-tests...",
"build": "webpack",
"test": "playwright test",
"test:int": "playwright test",
"test:vanilla": "playwright test src/tests/signals-vanilla",
"test:perf": "playwright test src/tests/performance",
"test:custom": "playwright test src/tests/custom",
Expand Down
11 changes: 9 additions & 2 deletions packages/signals/signals/src/core/processor/processor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { logger } from '../../lib/logger'
import { Signal } from '@segment/analytics-signals-runtime'
import { AnyAnalytics } from '../../types'
import { MethodName, Sandbox } from './sandbox'
import { AnalyticsMethodCalls, MethodName, Sandbox } from './sandbox'

export class SignalEventProcessor {
private sandbox: Sandbox
Expand All @@ -12,7 +12,14 @@
}

async process(signal: Signal, signals: Signal[]) {
const analyticsMethodCalls = await this.sandbox.process(signal, signals)
let analyticsMethodCalls: AnalyticsMethodCalls
try {
analyticsMethodCalls = await this.sandbox.process(signal, signals)

Check warning on line 17 in packages/signals/signals/src/core/processor/processor.ts

View check run for this annotation

Codecov / codecov/patch

packages/signals/signals/src/core/processor/processor.ts#L16-L17

Added lines #L16 - L17 were not covered by tests
} catch (err) {
// in practice, we should never hit this error, but if we do, we should log it.
console.error('Error processing signal', { signal, signals }, err)
return

Check warning on line 21 in packages/signals/signals/src/core/processor/processor.ts

View check run for this annotation

Codecov / codecov/patch

packages/signals/signals/src/core/processor/processor.ts#L20-L21

Added lines #L20 - L21 were not covered by tests
}

for (const methodName in analyticsMethodCalls) {
const name = methodName as MethodName
Expand Down
Loading