Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
13 changes: 13 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Unit Tests # name of the test

on: [push] # the Github Action will activate "on" the event that you "push" to the repo

jobs: # the things being executed
tests: # the name of your status check, will become important when you do branch protection
runs-on: ubuntu-latest # which device on Github's server that you are running the Actions on
steps:
- uses: actions/checkout@v4 # using version 4 of Actions
- name: Install Dependencies
run: npm install
- name: Unit Test
run: npm test ./__tests__/sum.test.js # the actual testing line
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.DS_Store
.DS_Store
node_modules/
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
# Lab 5 - Starter

Members: David De Santiago - A17001592

- My "expose.js" [here](https://ddesantiag0.github.io/Lab5_Starter/expose.html)
- My "explore.js" [here](https://ddesantiag0.github.io/Lab5_Starter/explore.html)

## Check Your Understanding

### Question 1
Would you use a unit test to test the “message” feature of a messaging application? Why or why not? For this question, assume the “message” feature allows a user to write and send a message to another user.

**Answer:**
Unit testing might not be the best choice for testing the entire "message" feature due to its reliance on multiple interacting components. However, unit tests are suitable for testing individual parts of the feature such as the message formatting and validation functions.

### Question 2
Would you use a unit test to test the “max message length” feature of a messaging application? Why or why not? For this question, assume the “max message length” feature prevents the user from typing more than 80 characters.

**Answer:**
Yes, unit testing is appropriate for the "max message length" feature. This feature's functionality is isolated and can be precisely defined and tested without external dependencies, making it ideal for unit testing.
6 changes: 6 additions & 0 deletions __tests__/sum.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
// sum.test.js
import { sum } from '../code-to-unit-test/sum';

test('adds 1 + 2 to equal 3', () => {
// TODO
expect(sum(1 + 2)).toBe(3);
});

test('adds 1 + 2 to equal 3', () => {
expect(sum(1,2)).toBe(3); //should be wrong
});
79 changes: 79 additions & 0 deletions __tests__/unit.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,82 @@ import {
} from '../code-to-unit-test/unit-test-me';

// TODO - Part 2
// Tests for isPhoneNumber
describe('isPhoneNumber', () => {
test('validates correct phone number format', () => {
expect(isPhoneNumber('123-456-7890')).toBe(true);
});
test('validates another correct phone number format', () => {
expect(isPhoneNumber('(123) 456-7890')).toBe(true);
});
test('rejects incorrect phone number without dashes', () => {
expect(isPhoneNumber('1234567890')).toBe(false);
});
test('rejects incorrect phone number with too few digits', () => {
expect(isPhoneNumber('123-45-6789')).toBe(false);
});
});

// Tests for isEmail
describe('isEmail', () => {
test('validates correct email format', () => {
expect(isEmail('test@example.com')).toBe(true);
});
test('validates another correct email format', () => {
expect(isEmail('hello.world@domain.co.uk')).toBe(true);
});
test('rejects missing domain email', () => {
expect(isEmail('test@')).toBe(false);
});
test('rejects email without "@" symbol', () => {
expect(isEmail('testexample.com')).toBe(false);
});
});

// Tests for isStrongPassword
describe('isStrongPassword', () => {
test('validates strong password with special characters', () => {
expect(isStrongPassword('Example123!')).toBe(true);
});
test('validates strong password with underscore', () => {
expect(isStrongPassword('Strong_Pass1')).toBe(true);
});
test('rejects weak password with fewer characters', () => {
expect(isStrongPassword('examp')).toBe(false);
});
test('rejects password without numbers or special characters', () => {
expect(isStrongPassword('WeakPassword')).toBe(false);
});
});

// Tests for isDate
describe('isDate', () => {
test('validates correct date format MM/DD/YYYY', () => {
expect(isDate('04/12/2021')).toBe(true);
});
test('validates correct date format MM/D/YYYY', () => {
expect(isDate('04/2/2021')).toBe(true);
});
test('rejects incorrect date format with month name', () => {
expect(isDate('April 12, 2021')).toBe(false);
});
test('rejects incorrect format without year', () => {
expect(isDate('04/12')).toBe(false);
});
});

// Tests for isHexColor
describe('isHexColor', () => {
test('validates correct 6-digit hex color', () => {
expect(isHexColor('#FFFFFF')).toBe(true);
});
test('validates correct 3-digit hex color', () => {
expect(isHexColor('#FFF')).toBe(true);
});
test('rejects hex color without #', () => {
expect(isHexColor('FFFFFF')).toBe(false);
});
test('rejects incorrect hex color with non-hex characters', () => {
expect(isHexColor('#ZZZZZZ')).toBe(false);
});
});
52 changes: 49 additions & 3 deletions assets/scripts/explore.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,53 @@
// explore.js
// resources: https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis

window.addEventListener('DOMContentLoaded', init);
window.addEventListener("DOMContentLoaded", init);

function init() {
// TODO
}
const synth = window.speechSynthesis;
const textArea = document.getElementById('text-to-speak');
const voiceSelect = document.getElementById('voice-select');
const speakButton = document.querySelector('button');
const faceImage = document.querySelector('img');
let voices = [];

function populateVoices() {
voices = synth.getVoices();
voiceSelect.innerHTML = '';
voices.forEach((voice) => {
const option = document.createElement('option');
option.textContent = `${voice.name} (${voice.lang})${voice.default ? ' — DEFAULT' : ''}`;
option.setAttribute('data-name', voice.name);
option.setAttribute('data-lang', voice.lang);
voiceSelect.appendChild(option);
});
}

populateVoices();
if (synth.onvoiceschanged !== undefined) {
synth.onvoiceschanged = populateVoices;
}

function speak() {
if (synth.speaking) {
console.error('speechSynthesis.speaking');
return;
}
if (textArea.value !== '') {
const utterance = new SpeechSynthesisUtterance(textArea.value);
const selectedVoiceName = voiceSelect.selectedOptions[0].getAttribute('data-name');
utterance.voice = voices.find(voice => voice.name === selectedVoiceName);

utterance.onstart = () => {
faceImage.src = 'assets/images/smiling-open.png';
};
utterance.onend = () => {
faceImage.src = 'assets/images/smiling.png';
};

synth.speak(utterance);
}
}

speakButton.addEventListener('click', speak);
}
55 changes: 54 additions & 1 deletion assets/scripts/expose.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,58 @@
window.addEventListener('DOMContentLoaded', init);

function init() {
// TODO
// Get references to DOM elements
const hornSelectElement = document.getElementById('horn-select');
const volumeSliderElement = document.getElementById('volume');
const playButtonElement = document.querySelector('button');
const audioElement = document.querySelector('audio');
const hornImageElement = document.querySelector('#expose img');
const volumeIconElement = document.querySelector('#volume-controls img');

// Event listener for horn selection
hornSelectElement.addEventListener('change', function() {
const selectedHorn = hornSelectElement.value;
hornImageElement.src = `assets/images/${selectedHorn}.svg`;
hornImageElement.alt = selectedHorn;
audioElement.src = `assets/audio/${selectedHorn}.mp3`;
});

// Event listener for volume slider
volumeSliderElement.addEventListener('input', function() {
const volumeValue = volumeSliderElement.value;
audioElement.volume = volumeValue / 100;

if (volumeValue == 0) {
volumeIconElement.src = 'assets/icons/volume-level-0.svg';
volumeIconElement.alt = 'Volume level 0';
} else if (volumeValue < 33) {
volumeIconElement.src = 'assets/icons/volume-level-1.svg';
volumeIconElement.alt = 'Volume level 1';
} else if (volumeValue < 67) {
volumeIconElement.src = 'assets/icons/volume-level-2.svg';
volumeIconElement.alt = 'Volume level 2';
} else {
volumeIconElement.src = 'assets/icons/volume-level-3.svg';
volumeIconElement.alt = 'Volume level 3';
}
});

// Event listener for play button
playButtonElement.addEventListener('click', function() {
audioElement.play();
if (hornSelectElement.value === 'party-horn') {
const jsConfetti = new JSConfetti();
jsConfetti.addConfetti({
confettiRadius: 6,
confettiNumber: 300,
spread: 360,
startVelocity: 50,
gravity: 1,
origin: {
x: 0.5,
y: 0.5
}
});
}
});
}