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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 27 additions & 13 deletions src/pages/activities/Calculator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ class Calculator extends React.Component {
let op = [];
let temp = this.state.screenValue1.toString();
if(a === "=") {
console.log(temp)
for (let j = 0; j < temp.length; j++) {
if(temp[j] !== '/' && temp[j] !== 'x' && temp[j] !== '-' && temp[j] !== '+') {
r = `${r}${temp[j]}`
Expand All @@ -26,7 +25,6 @@ class Calculator extends React.Component {
r = ''
}
}
console.log(arr)
arr.push(r)
if(arr[0] === '' && op[0] === '-') {
arr[1]=`${op[0]}${arr[1]}`
Expand All @@ -36,13 +34,10 @@ class Calculator extends React.Component {
if(arr[0] === '') {
arr[0] = 0
}
console.log(arr)
r = '';
for(let x1 = 0; x1 < arr.length; x1++) {
arr[x1] = parseFloat(arr[x1])
}
console.log(arr)
console.log(op)
for(let x3 = 0; x3 < arr.length; x3++) {
if(isNaN(arr[x3])) {
arr[x3+1] = -arr[x3+1]
Expand All @@ -53,16 +48,35 @@ class Calculator extends React.Component {
if(op.length === 0){
return
}

// Two-pass algorithm for order of operations (PEMDAS/BODMAS)
// First pass: Process multiplication and division (left to right)
for(let b = 0; b < op.length; b++) {
if(op[b] === '/') {r = arr[0] / arr[1]; arr.shift(); arr[0] = r}
if(op[b] === 'x') {r = arr[0] * arr[1]; arr.shift(); arr[0] = r}
if(op[b] === '-') {r = arr[0] - arr[1]; arr.shift(); arr[0] = r}
if(op[b] === '+') {r = arr[0] + arr[1]; arr.shift(); arr[0] = r}
console.log(r)
if(op[b] === '/' || op[b] === 'x') {
if(op[b] === '/') {
r = arr[b] / arr[b+1];
} else {
r = arr[b] * arr[b+1];
}
// Replace the two operands with the result
arr.splice(b, 2, r);
// Remove the operator
op.splice(b, 1);
// Adjust index since we removed an element
b--;
}
}
console.log(r)
if(this.state.screenValue1[0] === 0) {
console.log('doin something funny')

// Second pass: Process addition and subtraction (left to right)
for(let b = 0; b < op.length; b++) {
if(op[b] === '-') {
r = arr[b] - arr[b+1];
} else if(op[b] === '+') {
r = arr[b] + arr[b+1];
}
arr.splice(b, 2, r);
op.splice(b, 1);
b--;
}
r = r.toString()
while(r.length > 15) {
Expand Down
250 changes: 250 additions & 0 deletions src/pages/activities/__tests__/Calculator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import Calculator from '../Calculator';

describe('Calculator Order of Operations', () => {
describe('PEMDAS/BODMAS - Multiplication and Division before Addition and Subtraction', () => {
test('should multiply before adding: 2 + 3 × 4 = 14', () => {
render(<Calculator />);

// Clear calculator first
fireEvent.click(screen.getByText('AC'));

// Enter: 2 + 3 × 4 =
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('+'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('x'));
fireEvent.click(screen.getByText('4'));
fireEvent.click(screen.getByText('='));

const display = screen.getByText('14');
expect(display).toBeInTheDocument();
});

test('should divide before subtracting: 10 - 8 / 2 = 6', () => {
const { container } = render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: 10 - 8 / 2 =
fireEvent.click(screen.getByText('1'));
fireEvent.click(screen.getByText('0'));
fireEvent.click(screen.getByText('-'));
fireEvent.click(screen.getByText('8'));
fireEvent.click(screen.getByText('/'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('='));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('6');
});

test('should multiply before adding (reversed): 5 + 2 × 3 = 11', () => {
render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: 5 + 2 × 3 =
fireEvent.click(screen.getByText('5'));
fireEvent.click(screen.getByText('+'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('x'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('='));

const display = screen.getByText('11');
expect(display).toBeInTheDocument();
});

test('should divide before subtracting: 12 - 3 / 3 = 11', () => {
render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: 12 - 3 / 3 =
fireEvent.click(screen.getByText('1'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('-'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('/'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('='));

const display = screen.getByText('11');
expect(display).toBeInTheDocument();
});
});

describe('Multiple operations with mixed precedence', () => {
test('should handle: 2 + 3 × 4 - 5 = 9', () => {
const { container } = render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: 2 + 3 × 4 - 5 =
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('+'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('x'));
fireEvent.click(screen.getByText('4'));
fireEvent.click(screen.getByText('-'));
fireEvent.click(screen.getByText('5'));
fireEvent.click(screen.getByText('='));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('9');
});

test('should handle: 5 + 2 × 3 - 4 / 2 = 9', () => {
const { container } = render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: 5 + 2 × 3 - 4 / 2 =
fireEvent.click(screen.getByText('5'));
fireEvent.click(screen.getByText('+'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('x'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('-'));
fireEvent.click(screen.getByText('4'));
fireEvent.click(screen.getByText('/'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('='));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('9');
});
});

describe('Same precedence operations (left to right)', () => {
test('should process left to right for same precedence: 10 - 5 - 2 = 3', () => {
const { container } = render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: 10 - 5 - 2 =
fireEvent.click(screen.getByText('1'));
fireEvent.click(screen.getByText('0'));
fireEvent.click(screen.getByText('-'));
fireEvent.click(screen.getByText('5'));
fireEvent.click(screen.getByText('-'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('='));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('3');
});

test('should handle division and multiplication left to right: 12 / 3 × 2 = 8', () => {
const { container } = render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: 12 / 3 × 2 =
fireEvent.click(screen.getByText('1'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('/'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('x'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('='));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('8');
});

test('should handle multiplication and division left to right: 2 × 6 / 3 = 4', () => {
const { container } = render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: 2 × 6 / 3 =
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('x'));
fireEvent.click(screen.getByText('6'));
fireEvent.click(screen.getByText('/'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('='));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('4');
});
});

describe('Edge cases and special scenarios', () => {
test('should handle decimal operations with order of operations: 5 + 2.5 × 2 = 10', () => {
const { container } = render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: 5 + 2.5 × 2 =
fireEvent.click(screen.getByText('5'));
fireEvent.click(screen.getByText('+'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('.'));
fireEvent.click(screen.getByText('5'));
fireEvent.click(screen.getByText('x'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('='));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('10');
});

test('should handle negative numbers: -5 + 3 × 2 = 1', () => {
const { container } = render(<Calculator />);

fireEvent.click(screen.getByText('AC'));

// Enter: -5 + 3 × 2 =
fireEvent.click(screen.getByText('-'));
fireEvent.click(screen.getByText('5'));
fireEvent.click(screen.getByText('+'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('x'));
fireEvent.click(screen.getByText('2'));
fireEvent.click(screen.getByText('='));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('1');
});
});

describe('Basic calculator functionality', () => {
test('should display initial value of 0', () => {
const { container } = render(<Calculator />);
const display = container.querySelector('#display');
expect(display).toHaveTextContent('0');
});

test('should clear display when AC is clicked', () => {
const { container } = render(<Calculator />);

// Enter some numbers
fireEvent.click(screen.getByText('5'));
fireEvent.click(screen.getByText('8'));

// Clear
fireEvent.click(screen.getByText('AC'));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('0');
});

test('should handle simple addition: 5 + 3 = 8', () => {
const { container } = render(<Calculator />);

fireEvent.click(screen.getByText('AC'));
fireEvent.click(screen.getByText('5'));
fireEvent.click(screen.getByText('+'));
fireEvent.click(screen.getByText('3'));
fireEvent.click(screen.getByText('='));

const display = container.querySelector('#display');
expect(display).toHaveTextContent('8');
});
});
});