Skip to content

Commit

Permalink
feat: finish confirm code page
Browse files Browse the repository at this point in the history
  • Loading branch information
hdev14 committed Feb 11, 2024
1 parent 227ee44 commit 850668f
Show file tree
Hide file tree
Showing 16 changed files with 282 additions and 154 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ NODE_ENV=development

SERVER_PORT=8000
SERVER_DOMAIN=''
SERVER_URL='http://locahost:8000'

DB_HOST=localhost
DB_PORT=5432
Expand Down
10 changes: 9 additions & 1 deletion script.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,12 @@ CREATE TABLE alerts (
min_amount float DEFAULT 0,
CONSTRAINT alerts_pk PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users(id)
);
);

CREATE TABLE user_confirmation_codes (
id VARCHAR(36) NOT NULL,
user_id VARCHAR(36) NOT NULL,
code VARCHAR(4) NOT NULL,
CONSTRAINT user_confirmation_codes_pk PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users(id)
);
89 changes: 89 additions & 0 deletions src/application/pages/confirm-code.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { faker } from '@faker-js/faker/locale/pt_BR';
import { expect, test } from '@playwright/test';

test.describe('Confirm Code Page', () => {
let user_id = '';

const user = {
name: faker.person.fullName(),
email: faker.internet.email(),
password: `${faker.string.alphanumeric(10)}!@#$`,
phone_number: faker.string.numeric(11),
};

test.beforeAll(async ({ request }) => {
const response = await request.post('/api/users', {
data: user,
headers: { 'Content-Type': 'application/json' },
});

const data = await response.json();

user_id = data.id;
});

test.afterAll(async ({ request }) => {
await request.delete(`/api/users/${user_id}`);
});

test('should validate the code field', async ({ page }) => {
await page.goto(`/pages/confirm-code?email=${user.email}`);

const invalid_code = faker.string.numeric(3);

const code_input = page.getByTestId('code');
await code_input.fill(invalid_code);
await code_input.blur();

const code_error_message = page.getByTestId('code-error-messages').first();

await expect(code_error_message).toContainText('O texto precisa ter pelo menos 4 caracteres.');
});

test('should not allow the user to go to /pages/confirm-code if captcha failed', async ({ page }) => {
await page.goto(`/pages/confirm-code?email=${user.email}`);

await page.route('*/**/api/auth/captcha', async (route) => {
await route.fulfill({ status: 403 });
});

const code_input = page.getByTestId('code');
await code_input.fill(faker.string.numeric(4));

const email_input = page.getByTestId('email');
const email_value = await email_input.inputValue();

const submit_button = page.getByTestId('confirm-code-submit');
await submit_button.click();

expect(email_value).toEqual(user.email);
expect(page).toHaveURL(`/pages/confirm-code?email=${user.email}`);
});

test("should alert the user if code doesn't exist", async ({ page, baseURL }) => {
await page.goto(`/pages/confirm-code?email=${user.email}`);

const code_input = page.getByTestId('code');
await code_input.fill(faker.string.numeric(4));

const email_input = page.getByTestId('email');
const email_value = await email_input.inputValue();

const submit_button = page.getByTestId('confirm-code-submit');
await submit_button.click();

await page.waitForResponse(`${baseURL}/forms/confirm-code`);

const alert_message = page.getByTestId('alert-message');
const text = await alert_message.innerText();

expect(email_value).toEqual(user.email);
expect(text).toBe('Código não encontrado.');
});

test("should redirect user to /pages/login if query param doesn't have email", async ({ page }) => {
await page.goto('/pages/confirm-code');

expect(page).toHaveURL('/pages/login');
});
});
22 changes: 21 additions & 1 deletion src/application/pages/confirm-code.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
{{> _head}}
<main>
<h1>{{title}}</h1>

<form id="confirm-code-form" data-testid="confirm-code-form" method="post" action="/forms/confirm-code">
<input id="code" type="text" name="code" data-testid="code" />
<ul id="code-error-messages" data-testid="code-error-messages"></ul>

<input hidden="email" type="email" name="email" data-testid="email" value="{{email}}" />

<button type="submit" data-testid="confirm-code-submit">
Confirm code
</button>
</form>
</main>

<script>

new Form(
document.getElementById('confirm-code-form'),
[
{
input_element: document.getElementById('code'),
error_message_element: document.getElementById('code-error-messages'),
rules: ['required', 'min:4']
},
]
).init(true);
</script>
{{> _footer}}
4 changes: 2 additions & 2 deletions src/application/pages/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ <h1>{{title}}</h1>
</main>

<script>
new LoginForm(
new Form(
document.getElementById('login-form'),
[
{
Expand All @@ -30,6 +30,6 @@ <h1>{{title}}</h1>
rules: ['required', 'min:8', 'password']
}
]
).init();
).init(true);
</script>
{{> _footer}}
1 change: 0 additions & 1 deletion src/application/pages/partials/_head.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

<!-- global scripts -->
<script type="application/javascript" src="https://unpkg.com/js-cookie@3.0.5/dist/js.cookie.min.js"></script>
<script type="application/javascript" src="/js/form.js"></script>

{{> components/links}}
{{> components/scripts}}
Expand Down
19 changes: 5 additions & 14 deletions src/application/pages/signup.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { faker } from '@faker-js/faker/locale/pt_BR';
import { expect, test } from '@playwright/test';

test.describe('Signup Page', () => {
let user_id = '';
const user = {
name: faker.person.fullName(),
email: faker.internet.email(),
Expand All @@ -11,18 +10,10 @@ test.describe('Signup Page', () => {
};

test.beforeAll(async ({ request }) => {
const response = await request.post('/api/users', {
await request.post('/api/users', {
data: user,
headers: { 'Content-Type': 'application/json' },
});

const data = await response.json();

user_id = data.id;
});

test.afterAll(async ({ request }) => {
await request.delete(`/api/users/${user_id}`);
});

test.beforeEach(async ({ page }) => {
Expand Down Expand Up @@ -88,7 +79,7 @@ test.describe('Signup Page', () => {
await expect(phone_number_error_message).toContainText('O campo precisa ser um telefone válido.');
});

test('should not allow the user to go to /pages/index if captcha failed', async ({ page }) => {
test('should not allow the user to go to /pages/confirm-code if captcha failed', async ({ page }) => {
await page.route('*/**/api/auth/captcha', async (route) => {
await route.fulfill({ status: 403 });
});
Expand All @@ -111,7 +102,7 @@ test.describe('Signup Page', () => {
expect(page).toHaveURL('/pages/signup');
});

test('should redirect the user to /pages/login if captcha succeed', async ({ page }) => {
test('should redirect the user to /pages/confirm-code if captcha succeed', async ({ page }) => {
const name_input = page.getByTestId('signup-name');
await name_input.fill(faker.person.fullName());

Expand All @@ -126,9 +117,9 @@ test.describe('Signup Page', () => {

const submit_button = page.getByTestId('signup-submit');
await submit_button.click();
await page.waitForURL('**/pages/confirm-code');
await page.waitForTimeout(3000);

expect(page).toHaveURL('/pages/confirm-code');
expect(page).toHaveTitle('Confirmar código!');
});

test('should not register the same email twice', async ({ page, baseURL }) => {
Expand Down
4 changes: 2 additions & 2 deletions src/application/pages/signup.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ <h1>{{title}}</h1>
const phone_number_input = document.getElementById('phone-number');
const mask = IMask(phone_number_input, { mask: '(00)00000-0000' });

new SignupForm(
new Form(
document.getElementById('signup-form'),
[
{
Expand All @@ -49,6 +49,6 @@ <h1>{{title}}</h1>
rules: ['required', 'min:8', 'password']
}
]
).init();
).init(true);
</script>
{{> _footer}}
58 changes: 51 additions & 7 deletions src/application/public/js/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,26 @@ class Form {
fields = [];

/**
* @property {Element} form
* @property {Element} form_element
*/
form_element;

/**
* @param {Element} form
* @param {Element} form_element
* @param {Object[]} fields
* @param {Element} fields[].input_element
* @param {Element} fields[].error_message_element
*/
constructor(form, fields) {
this.form_element = form;
constructor(form_element, fields) {
this.form_element = form_element;
this.fields = fields;
}

init() {
/**
*
* @param {boolean} captcha
*/
init(captcha = false) {
this.fields.forEach(({ input_element, error_message_element, rules }) => {
input_element.addEventListener('blur', this.validateInput(
error_message_element,
Expand All @@ -33,6 +37,10 @@ class Form {
).bind(this));
});

if (captcha) {
this.form_element.addEventListener('submit', this.submitCaptcha.bind(this));
return;
}
this.form_element.addEventListener('submit', this.submit.bind(this));
}

Expand All @@ -49,8 +57,44 @@ class Form {
* @param {Event} event
*/
submit(event) {
console.log(event);
throw new Error('Not implemented');
event.preventDefault();

if (this.hasErrors()) {
return;
}

this.form_element.submit();
}

/**
*
* @param {Event} event
*/
submitCaptcha(event) {
event.preventDefault();

if (this.hasErrors()) {
return;
}

grecaptcha.ready(async () => {
const token = await grecaptcha.execute(
'6LdAc2UpAAAAAObuHow9pOS5dy0coRW11AKKiWJA',
{ action: 'submit' },
);

const response = await fetch('/api/auth/captcha', {
method: 'POST',
body: JSON.stringify({ token }),
headers: {
'Content-Type': 'application/json',
},
});

if (response.status === 204) {
this.form_element.submit();
}
});
}

/**
Expand Down
29 changes: 0 additions & 29 deletions src/application/public/js/login_form.js

This file was deleted.

29 changes: 0 additions & 29 deletions src/application/public/js/signup_form.js

This file was deleted.

Loading

0 comments on commit 850668f

Please sign in to comment.