From 22feb658e4cc78076701d06e66b017403f0db3ff Mon Sep 17 00:00:00 2001 From: Helen Martmaa Date: Wed, 22 Apr 2026 23:04:46 +0300 Subject: [PATCH 1/2] Task 1. app.test.js file updating with tests, images of test run results added. --- Task1_npx_jest_app_test.PNG | Bin 0 -> 21366 bytes Task1_npx_test.PNG | Bin 0 -> 17526 bytes app.test.js | 197 ++++++++++++++++++++++++++++++++++-- 3 files changed, 187 insertions(+), 10 deletions(-) create mode 100644 Task1_npx_jest_app_test.PNG create mode 100644 Task1_npx_test.PNG diff --git a/Task1_npx_jest_app_test.PNG b/Task1_npx_jest_app_test.PNG new file mode 100644 index 0000000000000000000000000000000000000000..33dd0b8c3e20b5136265b22594a2f014d1d7564f GIT binary patch literal 21366 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 literal 0 HcmV?d00001 diff --git a/Task1_npx_test.PNG b/Task1_npx_test.PNG new file mode 100644 index 0000000000000000000000000000000000000000..56c9f57c084f215b44bc617857581a6ae749c0bd GIT binary patch literal 17526 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 literal 0 HcmV?d00001 diff --git a/app.test.js b/app.test.js index f1b561d..844f9fe 100644 --- a/app.test.js +++ b/app.test.js @@ -22,13 +22,35 @@ describe('given correct username and password', () => { password: 'Password123', email: 'student@example.com' }) - expect(response.body.userId).toBeDefined(); + expect(response.body.userId).toBeDefined() }) - // test response content type? - // test response message - // test response user id value - // ... + test('returns content type json', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.headers['content-type']).toContain('application/json') + }) + + test('returns success message', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.body.message).toBe('Valid User') + }) + + test('returns user id value 1', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.body.userId).toBe('1') + }) }) describe('given incorrect or missing username and password', () => { @@ -41,9 +63,164 @@ describe('given incorrect or missing username and password', () => { expect(response.statusCode).toBe(400) }) - // test response message - // test that response does NOT have userId - // test incorrect username or password according to requirements - // test missing username or password - // ... + test('returns error message', async () => { + const response = await request(app).post('/users').send({ + username: 'user', + password: 'password', + email: 'not-an-email' + }) + expect(response.body.error).toBe('Invalid User') + }) + + test('does not return userId when user is invalid', async () => { + const response = await request(app).post('/users').send({ + username: 'user', + password: 'password', + email: 'not-an-email' + }) + expect(response.body.userId).toBeUndefined() + }) + + test('returns status 400 when username is too short', async () => { + const response = await request(app).post('/users').send({ + username: 'user1', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when username is too long', async () => { + const response = await request(app).post('/users').send({ + username: 'a'.repeat(31), + password: 'Password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when username contains invalid characters', async () => { + const response = await request(app).post('/users').send({ + username: 'user_name', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is too short', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Pass12', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is missing uppercase letter', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is missing lowercase letter', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'PASSWORD123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is missing number', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password contains special characters', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123!', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email format is invalid', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'not-an-email' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email is missing @ symbol', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'studentexample.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email is missing domain extension', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email has too short extension', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example.x' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email is missing text before @', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: '@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when username is empty', async () => { + const response = await request(app).post('/users').send({ + username: '', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is empty', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: '', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email is missing', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123' + }) + expect(response.statusCode).toBe(400) + }) }) \ No newline at end of file From b80666abcf2f473f2b9fb4fd7b3fc00514ba6b98 Mon Sep 17 00:00:00 2001 From: Helen Martmaa Date: Wed, 22 Apr 2026 23:30:33 +0300 Subject: [PATCH 2/2] Task 2. Added mock tests for app. Run time for app.mock.test.js was about 5 times faster than app.test.js test run. --- Task2_npx_mock_test_run.PNG | Bin 0 -> 21376 bytes app.mock.test.js | 220 ++++++++++++++++++++++++++++++++---- 2 files changed, 201 insertions(+), 19 deletions(-) create mode 100644 Task2_npx_mock_test_run.PNG diff --git a/Task2_npx_mock_test_run.PNG b/Task2_npx_mock_test_run.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f38d33495dda621f9f31fa417fc382b4b4c3844e GIT binary patch literal 21376 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 p jest.fn()) + const createApp = require('./app') const request = require('supertest') const validateUsername = require('./validation/validateUsername') const validatePassword = require('./validation/validatePassword') +const validateEmail = require('./validation/validateEmail') + +const app = createApp(validateUsername, validatePassword, validateEmail) + +beforeEach(() => { + validateEmail.mockImplementation((email) => { + if (!email || typeof email !== 'string') return false -//Mock validateEmail to isolate tests -jest.mock('./validation/validateEmail', () => { - return jest.fn((email) => { - //Simulate real world simulation - if (!email || typeof email !== 'string') return false; - const re = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i; - return re.test(email); + const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i + return emailPattern.test(email) }) }) -const validateEmail = require('./validation/validateEmail') -const app = createApp(validateUsername, validatePassword, validateEmail) +afterEach(() => { + jest.clearAllMocks() +}) describe('given correct username and password', () => { test('return status 200', async () => { @@ -32,13 +37,35 @@ describe('given correct username and password', () => { password: 'Password123', email: 'student@example.com' }) - expect(response.body.userId).toBeDefined(); + expect(response.body.userId).toBeDefined() + }) + + test('returns content type json', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.headers['content-type']).toContain('application/json') }) - // test response content type? - // test response message - // test response user id value - // ... + test('returns success message', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.body.message).toBe('Valid User') + }) + + test('returns user id value 1', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.body.userId).toBe('1') + }) }) describe('given incorrect or missing username and password', () => { @@ -51,9 +78,164 @@ describe('given incorrect or missing username and password', () => { expect(response.statusCode).toBe(400) }) - // test response message - // test that response does NOT have userId - // test incorrect username or password according to requirements - // test missing username or password - // ... + test('returns error message', async () => { + const response = await request(app).post('/users').send({ + username: 'user', + password: 'password', + email: 'not-an-email' + }) + expect(response.body.error).toBe('Invalid User') + }) + + test('does not return userId when user is invalid', async () => { + const response = await request(app).post('/users').send({ + username: 'user', + password: 'password', + email: 'not-an-email' + }) + expect(response.body.userId).toBeUndefined() + }) + + test('returns status 400 when username is too short', async () => { + const response = await request(app).post('/users').send({ + username: 'user1', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when username is too long', async () => { + const response = await request(app).post('/users').send({ + username: 'a'.repeat(31), + password: 'Password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when username contains invalid characters', async () => { + const response = await request(app).post('/users').send({ + username: 'user_name', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is too short', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Pass12', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is missing uppercase letter', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is missing lowercase letter', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'PASSWORD123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is missing number', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password contains special characters', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123!', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email format is invalid', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'not-an-email' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email is missing @ symbol', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'studentexample.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email is missing domain extension', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email has too short extension', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: 'student@example.x' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email is missing text before @', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123', + email: '@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when username is empty', async () => { + const response = await request(app).post('/users').send({ + username: '', + password: 'Password123', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when password is empty', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: '', + email: 'student@example.com' + }) + expect(response.statusCode).toBe(400) + }) + + test('returns status 400 when email is missing', async () => { + const response = await request(app).post('/users').send({ + username: 'Username', + password: 'Password123' + }) + expect(response.statusCode).toBe(400) + }) }) \ No newline at end of file