Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
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
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
# Lab 5 - Starter
# Lab 5 - Starter

Link to pages site:

Answers for Explore pt. 3:


1) Yes, unit testing is highly recommended for this feature of a messaging application, because it allows you to test each component of the feature in isolation. Unit tests are designed to validate individual units of code to ensure they perform as expected under various conditions. In the context of a messaging feature, this could involve testing the functionality for creating, sending, and receiving messages independently. For example, you could test whether a message object is created correctly with all necessary attributes like sender, recipient, timestamp, and content. Additionally, you would verify that the send function correctly handles the message data, ensures it is routed to the intended recipient, and interacts appropriately with the database or server. Similarly, the process of receiving messages can be tested to confirm that messages are correctly retrieved and displayed to the recipient. By isolating these components in unit tests, developers can quickly identify and fix bugs in the messaging logic, enhancing the reliability and robustness of the application. Finally, unit tests can be automated and run frequently, providing continuous feedback during development and maintenance phases, ensuring that new changes do not break existing functionality.
2) Yes, using a unit test to test this feature of a messaging application is both appropriate and advantageous. This feature, which limits user inputs to no more than 80 characters, is ideally suited for unit testing because it involves a specific, isolated piece of functionality that can be tested independently of other components. In unit testing, you would simulate input scenarios where text is provided to the message input field, checking that the application correctly enforces the 80-character limit. This might include tests where the input exactly matches the limit, slightly exceeds it, or falls under it. The key is to ensure the application behaves as expected in each scenario, such as preventing additional characters from being entered or providing user feedback when the limit is exceeded. Unit testing this feature helps in early detection of errors, ensuring consistent behavior throughout development, and providing quick feedback to developers. Moreover, these tests can be automated and integrated into a continuous integration pipeline to ensure that subsequent changes to the code do not inadvertently break this functionality.
8 changes: 7 additions & 1 deletion __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(1 + 2).toBe(3);
});

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

// TODO - Part 2

// Test cases for isPhoneNumber
describe('isPhoneNumber', () => {
test('validates correct phone number "123-456-7890"', () => {
expect(isPhoneNumber('123-456-7890')).toBe(true);
});
test('validates correct phone number "(123) 456-7890"', () => {
expect(isPhoneNumber('(123) 456-7890')).toBe(true);
});
test('rejects incorrect phone number "12345-67890"', () => {
expect(isPhoneNumber('12345-67890')).toBe(false);
});
test('rejects incomplete phone number "456-7890"', () => {
expect(isPhoneNumber('456-7890')).toBe(false);
});
});

// Test cases for isEmail
describe('isEmail', () => {
test('validates correct email "email@example.com"', () => {
expect(isEmail('email@example.com')).toBe(true);
});
test('validates correct email "user.name@domain.com"', () => {
expect(isEmail('user.name@domain.com')).toBe(true);
});
test('rejects invalid email "email.com"', () => {
expect(isEmail('email.com')).toBe(false);
});
test('rejects invalid email "@example.com"', () => {
expect(isEmail('@example.com')).toBe(false);
});
});

// Test cases for isStrongPassword
describe('isStrongPassword', () => {
test('validates strong password "Abc1234"', () => {
expect(isStrongPassword('Abc1234')).toBe(true);
});
test('validates strong password "A1_b"', () => {
expect(isStrongPassword('A1_b')).toBe(true);
});
test('rejects weak password "abc"', () => {
expect(isStrongPassword('abc')).toBe(false);
});
test('rejects overly long password "1234567890123456"', () => {
expect(isStrongPassword('1234567890123456')).toBe(false);
});
});

// Test cases for isDate
describe('isDate', () => {
test('validates correct date "12/25/2021"', () => {
expect(isDate('12/25/2021')).toBe(true);
});
test('validates correct date "1/1/2020"', () => {
expect(isDate('1/1/2020')).toBe(true);
});
test('rejects incorrect date format "25/12/2021"', () => {
expect(isDate('25/12/2021')).toBe(false);
});
test('rejects invalid date "02/30/2020"', () => {
expect(isDate('02/30/2020')).toBe(false);
});
});

// Test cases for isHexColor
describe('isHexColor', () => {
test('validates correct hex color "#FFF"', () => {
expect(isHexColor('#FFF')).toBe(true);
});
test('validates correct hex color "#123ABC"', () => {
expect(isHexColor('#123ABC')).toBe(true);
});
test('rejects invalid hex color "123456"', () => {
expect(isHexColor('123456')).toBe(false);
});
test('rejects incorrect hex color "#XYZ123"', () => {
expect(isHexColor('#XYZ123')).toBe(false);
});
});
42 changes: 39 additions & 3 deletions assets/scripts/explore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,42 @@

window.addEventListener('DOMContentLoaded', init);

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

function populateVoiceList() {
voices = speechSynthesis.getVoices();
voiceSelect.innerHTML = '<option value="select" disabled selected>Select Voice:</option>';
voices.forEach((voice) => {
const option = document.createElement('option');
option.textContent = `${voice.name} (${voice.lang})`;
option.setAttribute('data-name', voice.name);
option.setAttribute('data-lang', voice.lang);
voiceSelect.appendChild(option);
});
}

populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}

button.addEventListener('click', () => {
const selectedVoiceName = voiceSelect.selectedOptions[0].getAttribute('data-name');
const utterance = new SpeechSynthesisUtterance(textArea.value);
const selectedVoice = voices.find(voice => voice.name === selectedVoiceName);

utterance.voice = selectedVoice;
utterance.onstart = () => {
img.src = 'assets/images/smiling-open.png';
};
utterance.onend = () => {
img.src = 'assets/images/smiling.png';
};
speechSynthesis.speak(utterance);
});
}
68 changes: 67 additions & 1 deletion assets/scripts/expose.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,71 @@
window.addEventListener('DOMContentLoaded', init);

function init() {
// TODO

function init() {
// Select elements
const hornSelect = document.getElementById('horn-select');
const audio = document.querySelector('audio');
const soundImage = document.querySelector('main img'); // Selects the first <img> in <main>
const volumeSlider = document.getElementById('volume');
const volumeIcon = document.querySelector('#volume-controls img'); // Selects the <img> inside the volume controls div
const playButton = document.querySelector('button');

// Maps for image and sound sources
const soundSources = {
'air-horn': 'assets/audio/air-horn.mp3',
'car-horn': 'assets/audio/car-horn.mp3',
'party-horn': 'assets/audio/party-horn.mp3'
};
const imageSources = {
'air-horn': 'assets/images/air-horn.svg',
'car-horn': 'assets/images/car-horn.svg',
'party-horn': 'assets/images/party-horn.svg'
};

// Event listener for horn selection
hornSelect.addEventListener('change', () => {
audio.src = soundSources[hornSelect.value];
soundImage.src = imageSources[hornSelect.value];
soundImage.alt = hornSelect.options[hornSelect.selectedIndex].text; // Sets alt text based on the selected option's text
});

// Event listener for volume changes
volumeSlider.addEventListener('input', () => {
audio.volume = volumeSlider.value / 100;
updateVolumeIcon(volumeSlider.value, volumeIcon);
});

// Event listener for playing sound
playButton.addEventListener('click', () => {
audio.play();
if (hornSelect.value === 'party-horn') {
playConfetti();
}
});
}

// Function to update volume icon
function updateVolumeIcon(volume, icon) {
if (volume >= 67) {
icon.src = 'assets/icons/volume-level-3.svg';
icon.alt = 'Volume level 3';
} else if (volume >= 33) {
icon.src = 'assets/icons/volume-level-2.svg';
icon.alt = 'Volume level 2';
} else if (volume > 0) {
icon.src = 'assets/icons/volume-level-1.svg';
icon.alt = 'Volume level 1';
} else {
icon.src = 'assets/icons/volume-level-0.svg';
icon.alt = 'Volume level 0';
}
}

// Function to play confetti
function playConfetti() {
const jsConfetti = new JSConfetti(); // Assumes JSConfetti is available globally
jsConfetti.addConfetti();
}

}
Binary file added merged.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added myError.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions node_modules/.bin/browserslist

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/create-jest

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/esparse

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/esvalidate

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/import-local-fixture

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/jest

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/js-yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/jsesc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/json5

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/node-which

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/parser

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/resolve

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/semver

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions node_modules/.bin/update-browserslist-db

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading