Skip to content

Commit c96f6d4

Browse files
authored
feat: Add unit tests for react package
2 parents b9a73e9 + 89de60d commit c96f6d4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+4785
-84
lines changed

.github/workflows/integration-tests.yml renamed to .github/workflows/core-integration-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Integration Tests
1+
name: Core Integration Tests
22

33
on:
44
push:

.github/workflows/unit-tests.yml renamed to .github/workflows/core-unit-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Unit Tests
1+
name: Core Unit Tests
22

33
on:
44
push:
@@ -31,4 +31,4 @@ jobs:
3131
run: pnpm install
3232

3333
- name: Run unit tests
34-
run: pnpm --filter @firebase-ui/core test
34+
run: pnpm --filter @firebase-ui/core test:unit
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: React Integration Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
integration-test:
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
node-version: [22.x]
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Use Node.js ${{ matrix.node-version }}
21+
uses: actions/setup-node@v4
22+
with:
23+
node-version: ${{ matrix.node-version }}
24+
25+
- name: Setup Java for Firebase Emulator
26+
uses: actions/setup-java@v4
27+
with:
28+
distribution: "temurin"
29+
java-version: "17"
30+
31+
- name: Install pnpm
32+
uses: pnpm/action-setup@v2
33+
with:
34+
version: 8
35+
36+
- name: Install dependencies
37+
run: pnpm install
38+
39+
- name: Build core package
40+
run: pnpm --filter @firebase-ui/core build
41+
42+
- name: Install Firebase Tools
43+
run: npm install -g firebase-tools
44+
45+
- name: Create Firebase config
46+
run: |
47+
cat > firebase.json << EOF
48+
{
49+
"emulators": {
50+
"auth": {
51+
"port": 9099
52+
},
53+
"ui": {
54+
"enabled": false
55+
}
56+
}
57+
}
58+
EOF
59+
60+
- name: Start Firebase Emulator and Run Integration Tests
61+
run: |
62+
firebase emulators:start &
63+
sleep 10
64+
pnpm --filter @firebase-ui/react test:integration
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: React Unit Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
unit-test:
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
node-version: [22.x]
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Use Node.js ${{ matrix.node-version }}
21+
uses: actions/setup-node@v4
22+
with:
23+
node-version: ${{ matrix.node-version }}
24+
25+
- name: Install pnpm
26+
uses: pnpm/action-setup@v2
27+
with:
28+
version: 8
29+
30+
- name: Install dependencies
31+
run: pnpm install
32+
33+
- name: Run unit tests
34+
run: pnpm --filter @firebase-ui/react test:unit

packages/firebaseui-core/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
"lint": "tsc --noEmit",
2424
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"",
2525
"clean": "rimraf dist",
26-
"test": "vitest run tests/unit",
27-
"test:watch": "vitest tests/unit",
26+
"test:unit": "vitest run tests/unit",
27+
"test:unit:watch": "vitest tests/unit",
2828
"test:integration": "vitest run tests/integration",
2929
"test:integration:watch": "vitest tests/integration",
30-
"test:all": "vitest run"
30+
"test": "vitest run"
3131
},
3232
"keywords": [
3333
"firebase",

packages/firebaseui-react/package.json

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222
"dev": "tsup --watch",
2323
"lint": "tsc --noEmit",
2424
"format": "prettier --write \"src/**/*.ts\"",
25-
"clean": "rimraf dist"
25+
"clean": "rimraf dist",
26+
"test:unit": "TEST_TYPE=unit vitest run tests/unit",
27+
"test:unit:watch": "TEST_TYPE=unit vitest tests/unit",
28+
"test:integration": "TEST_TYPE=integration vitest run tests/integration",
29+
"test:integration:watch": "TEST_TYPE=integration vitest tests/integration"
2630
},
2731
"peerDependencies": {
2832
"@firebase-ui/core": "workspace:*",
@@ -40,11 +44,18 @@
4044
"zod": "^3.24.1"
4145
},
4246
"devDependencies": {
47+
"@testing-library/jest-dom": "^6.4.3",
48+
"@testing-library/react": "^16.2.0",
49+
"@types/jsdom": "^21.1.7",
50+
"@types/node": "^22.13.8",
4351
"@types/react": "^19.0.8",
4452
"@types/react-dom": "^19.0.3",
4553
"@vitejs/plugin-react": "^4.3.4",
54+
"jsdom": "^26.0.0",
55+
"tsup": "^8.3.6",
4656
"typescript": "~5.6.2",
4757
"vite": "^6.0.5",
48-
"tsup": "^8.3.6"
58+
"vitest": "^3.0.8",
59+
"vitest-tsconfig-paths": "^3.4.1"
4960
}
5061
}

packages/firebaseui-react/src/auth/forms/email-link-form.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export function EmailLinkForm() {
2424
const translations = useTranslations();
2525
const [formError, setFormError] = useState<string | null>(null);
2626
const [emailSent, setEmailSent] = useState(false);
27+
const [firstValidationOccured, setFirstValidationOccured] = useState(false);
2728

2829
const emailLinkFormSchema = useMemo(
2930
() => createEmailLinkFormSchema(translations),
@@ -128,8 +129,17 @@ export function EmailLinkForm() {
128129
name={field.name}
129130
type="email"
130131
value={field.state.value}
131-
onBlur={field.handleBlur}
132-
onChange={(e) => field.handleChange(e.target.value)}
132+
onBlur={() => {
133+
setFirstValidationOccured(true);
134+
field.handleBlur();
135+
}}
136+
onInput={(e) => {
137+
field.handleChange((e.target as HTMLInputElement).value);
138+
if (firstValidationOccured) {
139+
field.handleBlur();
140+
form.update();
141+
}
142+
}}
133143
/>
134144
<FieldInfo field={field} />
135145
</label>

packages/firebaseui-react/src/auth/forms/email-password-form.tsx

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export function EmailPasswordForm({
3131
enableHandleExistingCredential,
3232
} = useConfig();
3333
const [formError, setFormError] = useState<string | null>(null);
34+
const [firstValidationOccured, setFirstValidationOccured] = useState(false);
3435

3536
// TODO: Do we need to memoize this?
3637
const emailFormSchema = useMemo(
@@ -102,8 +103,17 @@ export function EmailPasswordForm({
102103
name={field.name}
103104
type="email"
104105
value={field.state.value}
105-
onBlur={field.handleBlur}
106-
onChange={(e) => field.handleChange(e.target.value)}
106+
onBlur={() => {
107+
setFirstValidationOccured(true);
108+
field.handleBlur();
109+
}}
110+
onInput={(e) => {
111+
field.handleChange((e.target as HTMLInputElement).value);
112+
if (firstValidationOccured) {
113+
field.handleBlur();
114+
form.update();
115+
}
116+
}}
107117
/>
108118
<FieldInfo field={field} />
109119
</label>
@@ -149,8 +159,17 @@ export function EmailPasswordForm({
149159
name={field.name}
150160
type="password"
151161
value={field.state.value}
152-
onBlur={field.handleBlur}
153-
onChange={(e) => field.handleChange(e.target.value)}
162+
onBlur={() => {
163+
setFirstValidationOccured(true);
164+
field.handleBlur();
165+
}}
166+
onInput={(e) => {
167+
field.handleChange((e.target as HTMLInputElement).value);
168+
if (firstValidationOccured) {
169+
field.handleBlur();
170+
form.update();
171+
}
172+
}}
154173
/>
155174
<FieldInfo field={field} />
156175
</label>

packages/firebaseui-react/src/auth/forms/forgot-password-form.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export function ForgotPasswordForm({
2626
const { language } = useConfig();
2727
const [formError, setFormError] = useState<string | null>(null);
2828
const [emailSent, setEmailSent] = useState(false);
29+
const [firstValidationOccured, setFirstValidationOccured] = useState(false);
2930
const forgotPasswordFormSchema = useMemo(
3031
() => createForgotPasswordFormSchema(translations),
3132
[translations]
@@ -106,8 +107,17 @@ export function ForgotPasswordForm({
106107
name={field.name}
107108
type="email"
108109
value={field.state.value}
109-
onBlur={field.handleBlur}
110-
onChange={(e) => field.handleChange(e.target.value)}
110+
onBlur={() => {
111+
setFirstValidationOccured(true);
112+
field.handleBlur();
113+
}}
114+
onInput={(e) => {
115+
field.handleChange((e.target as HTMLInputElement).value);
116+
if (firstValidationOccured) {
117+
field.handleBlur();
118+
form.update();
119+
}
120+
}}
111121
/>
112122
<FieldInfo field={field} />
113123
</label>

packages/firebaseui-react/src/auth/forms/phone-form.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function PhoneNumberForm({
4040
const [selectedCountry, setSelectedCountry] = useState<CountryData>(
4141
countryData[0]
4242
);
43+
const [firstValidationOccured, setFirstValidationOccured] = useState(false);
4344

4445
const phoneFormSchema = useMemo(
4546
() =>
@@ -104,8 +105,17 @@ function PhoneNumberForm({
104105
name={field.name}
105106
type="tel"
106107
value={field.state.value}
107-
onBlur={field.handleBlur}
108-
onChange={(e) => field.handleChange(e.target.value)}
108+
onBlur={() => {
109+
setFirstValidationOccured(true);
110+
field.handleBlur();
111+
}}
112+
onInput={(e) => {
113+
field.handleChange((e.target as HTMLInputElement).value);
114+
if (firstValidationOccured) {
115+
field.handleBlur();
116+
phoneForm.update();
117+
}
118+
}}
109119
className="fui-phone-input__number-input"
110120
/>
111121
</div>
@@ -195,6 +205,7 @@ function VerificationForm({
195205
}: VerificationFormProps) {
196206
const { language } = useConfig();
197207
const translations = useTranslations();
208+
const [firstValidationOccured, setFirstValidationOccured] = useState(false);
198209

199210
const verificationFormSchema = useMemo(
200211
() =>
@@ -249,8 +260,17 @@ function VerificationForm({
249260
name={field.name}
250261
type="text"
251262
value={field.state.value}
252-
onBlur={field.handleBlur}
253-
onChange={(e) => field.handleChange(e.target.value)}
263+
onBlur={() => {
264+
setFirstValidationOccured(true);
265+
field.handleBlur();
266+
}}
267+
onInput={(e) => {
268+
field.handleChange((e.target as HTMLInputElement).value);
269+
if (firstValidationOccured) {
270+
field.handleBlur();
271+
verificationForm.update();
272+
}
273+
}}
254274
/>
255275
<FieldInfo field={field} />
256276
</label>

0 commit comments

Comments
 (0)