Skip to content

Commit b75107a

Browse files
Add CI/CD workflow for Vercel deployment and E2E testing; remove old workflow and update form tests to include phone number validation
1 parent 6c7123e commit b75107a

File tree

4 files changed

+129
-256
lines changed

4 files changed

+129
-256
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: CI/CD Workflow --> Deploy and Run E2E Tests
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
deploy-staging:
11+
name: Deploy to Vercel Staging
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout Code
16+
uses: actions/checkout@v3
17+
18+
- name: Install Vercel CLI
19+
run: npm install --global vercel@latest
20+
21+
- name: Pull Vercel Environment Information
22+
run: |
23+
vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN_MY_PROJECT }}
24+
25+
- name: Build Project Artifacts
26+
run: |
27+
vercel build --token=${{ secrets.VERCEL_TOKEN_MY_PROJECT }}
28+
29+
- name: Deploy to Staging
30+
id: deploy
31+
run: |
32+
DEPLOY_URL=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN_MY_PROJECT }} | tail -1)
33+
echo "DEPLOYMENT_URL=${DEPLOY_URL}" >> $GITHUB_ENV
34+
echo "Deployed to: $DEPLOY_URL"
35+
36+
env:
37+
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
38+
39+
e2e-tests:
40+
name: Run E2E Tests on Staging
41+
runs-on: ubuntu-latest
42+
needs: deploy-staging
43+
44+
steps:
45+
- name: Checkout Code
46+
uses: actions/checkout@v3
47+
48+
- name: Install pnpm
49+
run: npm install -g pnpm
50+
51+
- name: Install Dependencies
52+
run: pnpm install
53+
54+
- name: Install Playwright
55+
run: pnpm playwright install
56+
57+
- name: Run Playwright Tests
58+
run: pnpm playwright test
59+
env:
60+
BASE_URL: ${{ env.DEPLOYMENT_URL }}
61+
62+
deploy-prod:
63+
name: Deploy to Vercel Production
64+
runs-on: ubuntu-latest
65+
needs: e2e-tests
66+
if: github.ref == 'refs/heads/main'
67+
68+
steps:
69+
- name: Checkout Code
70+
uses: actions/checkout@v3
71+
72+
- name: Install Vercel CLI
73+
run: npm install --global vercel@latest
74+
75+
- name: Pull Vercel Environment Information
76+
run: |
77+
vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN_MY_PROJECT }}
78+
79+
- name: Build Project Artifacts
80+
run: |
81+
vercel build --prod --token=${{ secrets.VERCEL_TOKEN_MY_PROJECT }}
82+
83+
- name: Deploy to Production
84+
run: |
85+
vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN_MY_PROJECT }}
86+
87+
env:
88+
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}

.github/workflows/main.yml

Lines changed: 0 additions & 125 deletions
This file was deleted.

src/app/form/page.tsx

Lines changed: 22 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,16 @@
1-
// 'use client';
2-
3-
// import { useState } from 'react';
4-
5-
// export default function Form() {
6-
// const [name, setName] = useState('');
7-
// const [email, setEmail] = useState('');
8-
// const [message, setMessage] = useState('');
9-
// const [loading, setLoading] = useState(false);
10-
// const [error, setError] = useState('');
11-
12-
// const handleSubmit = async (e: React.FormEvent) => {
13-
// e.preventDefault();
14-
// setLoading(true);
15-
// setMessage('');
16-
// setError('');
17-
18-
// try {
19-
// const res = await fetch('/api/submit', {
20-
// method: 'POST',
21-
// headers: { 'Content-Type': 'application/json' },
22-
// body: JSON.stringify({ name, email }),
23-
// });
24-
25-
// if (!res.ok) throw new Error('Failed to submit');
26-
// const data = await res.json();
27-
// setMessage(data.message);
28-
// } catch {
29-
// setError('Submission failed. Please try again.');
30-
// } finally {
31-
// setLoading(false);
32-
// }
33-
// };
34-
35-
// const handleReset = () => {
36-
// setName('');
37-
// setEmail('');
38-
// setMessage('');
39-
// setError('');
40-
// };
41-
42-
// return (
43-
// <div>
44-
// <h1>Form Page</h1>
45-
// <form onSubmit={handleSubmit}>
46-
// <input
47-
// type="text"
48-
// placeholder="Enter your name"
49-
// value={name}
50-
// onChange={(e) => setName(e.target.value)}
51-
// />
52-
// <input
53-
// type="email"
54-
// placeholder="Enter your email"
55-
// value={email}
56-
// onChange={(e) => setEmail(e.target.value)}
57-
// />
58-
// <button type="submit" disabled={loading}>
59-
// {loading ? 'Submitting...' : 'Submit'}
60-
// </button>
61-
// <button type="button" onClick={handleReset}>Reset</button>
62-
// </form>
63-
// {message && <p style={{ color: 'green' }}>{message}</p>}
64-
// {error && <p style={{ color: 'red' }}>{error}</p>}
65-
// </div>
66-
// );
67-
// }
68-
69-
701
'use client';
712

723
import { useState } from 'react';
734

745
export default function Form() {
75-
const [formData, setFormData] = useState({ name: '', email: '' });
6+
const [formData, setFormData] = useState({ name: '', email: '', phone: '' });
767
const [message, setMessage] = useState('');
778
const [loading, setLoading] = useState(false);
789
const [error, setError] = useState('');
7910

8011
const validateInputs = () => {
81-
if (!formData.name.trim() || !formData.email.trim()) {
82-
setError('Both Name and Email are required');
12+
if (!formData.name.trim() || !formData.email.trim() || !formData.phone.trim()) {
13+
setError('All fields are required');
8314
return false;
8415
}
8516
if (formData.name.length > 50) {
@@ -90,6 +21,10 @@ export default function Form() {
9021
setError('Invalid email format');
9122
return false;
9223
}
24+
if (!/^\d{10}$/.test(formData.phone)) {
25+
setError('Phone number must be exactly 10 digits');
26+
return false;
27+
}
9328
return true;
9429
};
9530

@@ -116,8 +51,8 @@ export default function Form() {
11651
});
11752

11853
if (!res.ok) throw new Error('Failed to submit');
119-
const data = await res.json();
120-
setMessage(data.message);
54+
await res.json();
55+
setMessage(`✅ Hello ${formData.name}, your form has been submitted successfully!`);
12156
} catch {
12257
setError('Submission failed. Please try again.');
12358
} finally {
@@ -126,7 +61,7 @@ export default function Form() {
12661
};
12762

12863
const handleReset = () => {
129-
setFormData({ name: '', email: '' });
64+
setFormData({ name: '', email: '', phone: '' });
13065
setMessage('');
13166
setError('');
13267
};
@@ -135,25 +70,21 @@ export default function Form() {
13570
<div style={{ maxWidth: '400px', margin: 'auto', padding: '20px', border: '1px solid #ccc', borderRadius: '8px' }}>
13671
<h1>Form Page</h1>
13772
<form onSubmit={handleSubmit} noValidate>
138-
<input
139-
type="text"
140-
name="name"
141-
placeholder="Enter your name"
142-
value={formData.name}
143-
onChange={handleChange}
144-
/>
145-
<input
146-
type="email"
147-
name="email"
148-
placeholder="Enter your email"
149-
value={formData.email}
150-
onChange={handleChange}
151-
/>
152-
<button type="submit">{loading ? 'Submitting...' : 'Submit'}</button>
73+
<label htmlFor="name">Name:</label>
74+
<input type="text" id="name" name="name" placeholder="Enter your name" value={formData.name} onChange={handleChange} />
75+
76+
<label htmlFor="email">Email:</label>
77+
<input type="email" id="email" name="email" placeholder="Enter your email" value={formData.email} onChange={handleChange} />
78+
79+
<label htmlFor="phone">Phone:</label>
80+
<input type="tel" id="phone" name="phone" placeholder="Enter your phone number" value={formData.phone} onChange={handleChange} />
81+
82+
<button type="submit" disabled={loading}>{loading ? 'Submitting...' : 'Submit'}</button>
15383
<button type="button" onClick={handleReset}>Reset</button>
15484
</form>
85+
15586
<p id="error" style={{ color: 'red', visibility: error ? 'visible' : 'hidden' }}>{error}</p>
156-
<p id="message" style={{ color: 'purple', visibility: message ? 'visible' : 'hidden' }}>{message}</p>
87+
<p id="message" style={{ color: 'green', visibility: message ? 'visible' : 'hidden' }}>{message}</p>
15788
</div>
15889
);
15990
}

0 commit comments

Comments
 (0)