Skip to content

Commit

Permalink
Merge pull request #26 from gokulk16/r-21
Browse files Browse the repository at this point in the history
fix: copy paste last value pasting a promise
  • Loading branch information
gokulk16 authored Jun 21, 2024
2 parents 4352f76 + 464d328 commit 58d7167
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 34 deletions.
27 changes: 18 additions & 9 deletions js/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -505,45 +505,54 @@ function debounce(callback, wait) {
};
}

function isNotEmptyResult(item) {
function isNumberResult(item) {
return !_.isEmpty(item) && _.isNumber(item.result);
}

// find the last not empty value from evaluatedValues
function findLastValue(values) {
let lastValue = values.findLast(isNotEmptyResult);
let lastValue = values.findLast(isNumberResult);
return lastValue ? lastValue.result : null;
}

export async function copyLastValue(values) {
// copy the last result to clipboard
const lastValue = findLastValue(values);
let lastValue = findLastValue(values);
if (_.isNumber(lastValue)) {
lastValue = parseFloat(lastValue.toFixed(5));
copyValueToClipboard(lastValue);
return lastValue;
} else {
showToastMessage(`No result to copy`);
}
}

function onEditorKeydown(e) {
export async function copyPasteLastValue(values) {
let lastValue = await copyLastValue(values);
if (lastValue) {
insertNode(lastValue);
}
}

async function onEditorKeydown(e) {
let key = e.key;
// Order of below conditions matter since there is subset condition
if (key === "Enter" && e.shiftKey && (e.metaKey || e.ctrlKey)) {
let lastValue = copyLastValue(evaluatedValues);
if (lastValue) {
insertNode(lastValue);
}
// copy & paste last value
copyPasteLastValue(evaluatedValues);
} else if (key === "Enter" && (e.metaKey || e.ctrlKey)) {
// copy last value
copyLastValue(evaluatedValues);
} else if (key === "/" && (e.metaKey || e.ctrlKey)) {
// open/close help
toggleHelpOverlay();
} else if (key === "h" && (e.metaKey || e.ctrlKey)) {
// open/close history
toggleHistory();
}
}

function insertNode(...nodes) {
export function insertNode(...nodes) {
for (let node of nodes) {
document.execCommand("insertText", false, node);
}
Expand Down
73 changes: 55 additions & 18 deletions js/editor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import {
parse,
init,
getResultTokens,
insertNode,
copyPasteLastValue,
} from "./editor";
import { describe, it, expect, vi, test, beforeEach, afterEach } from "vitest";
import { describe, expect, vi, test, beforeEach, afterEach } from "vitest";
import * as Sentry from "@sentry/browser";
import path from "path";
import fs from "fs";
Expand Down Expand Up @@ -200,21 +202,21 @@ global.editor = {
global.historyData = [];

describe("testing loadPlaceholderData", () => {
it("should set placeholder text when no history data is present and currency conversions are loaded", async () => {
test("should set placeholder text when no history data is present and currency conversions are loaded", async () => {
editor.innerText = "";
await loadPlaceholderData(editor, historyData, true);

expect(editor.innerText).toContain("10 usd to inr");
});

it("should not set placeholder text when history data is present", async () => {
test("should not set placeholder text when history data is present", async () => {
editor.innerText = "";
await loadPlaceholderData(editor, [{ mockHistoryData: 1 }], true);

expect(editor.innerText).toBe("");
});

it("should set basic placeholder text when no currency conversions are loaded", async () => {
test("should set basic placeholder text when no currency conversions are loaded", async () => {
editor.innerText = "";
await loadPlaceholderData(editor, historyData, false);

Expand All @@ -236,26 +238,61 @@ Object.assign(navigator, {
});

describe("testing copyLastValue", () => {
it("should not attempt to copy when no numeric results are available", async () => {
test("should not attempt to copy when no numeric results are available", async () => {
global.evaluatedValues = [{ result: "text" }, { result: "some text" }];
await copyLastValue(global.evaluatedValues);
//arrange .not.toHaveBeenCalled tests first since all calls in the test file will be counted
expect(navigator.clipboard.writeText).not.toHaveBeenCalled();
});

it("should copy the last numeric result to the clipboard", async () => {
test("should copy the last numeric result to the clipboard", async () => {
global.evaluatedValues = [{ result: "text" }, { result: 42 }];
await copyLastValue(global.evaluatedValues);
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(42);
});

it("should copy the recent non empty vaue if available", async () => {
test("should copy the recent non empty vaue if available", async () => {
global.evaluatedValues = [{ result: 21 }, { result: "" }];
await copyLastValue(global.evaluatedValues);
expect(navigator.clipboard.writeText).toHaveBeenCalled(21);
});
});

describe("testing copyPasteLastValue", () => {
Object.assign(document, {
execCommand: vi.fn(),
});

test("should not attempt to copy since no numeric results are available", async () => {
global.evaluatedValues = [{ result: "text" }, { result: "some text" }];
await copyPasteLastValue(evaluatedValues);
//arrange .not.toHaveBeenCalled tests first since all calls in the test file will be counted
expect(document.execCommand).not.toHaveBeenCalled();
});

test("should paste the last numeric results available", async () => {
global.evaluatedValues = [{ result: 2 }, { result: "some text" }];
await copyPasteLastValue(evaluatedValues);
expect(document.execCommand).toHaveBeenCalledWith("insertText", false, 2);
});
});

describe("Testing insertNode", () => {
Object.assign(document, {
execCommand: vi.fn(),
});
test("should insert a new node with the given value into the editor", () => {
const value = "new value";
insertNode(value);

expect(document.execCommand).toHaveBeenCalledWith(
"insertText",
false,
"new value"
);
});
});

describe("testing getTitle", () => {
test("Return full string when length is less than or equal to 30", () => {
const result = getTitle("This is a short string");
Expand All @@ -282,7 +319,7 @@ vi.mock("@sentry/browser", () => ({
}));

describe("Testing initSentry", () => {
it("should initialize Sentry with the correct configuration", async () => {
test("should initialize Sentry with the correct configuration", async () => {
await initSentry();

expect(Sentry.init).toHaveBeenCalledWith({
Expand All @@ -309,7 +346,7 @@ describe("testing parse", () => {
global.output = document.getElementById("output");
});

it("should update the output value to 4", async () => {
test("should update the output value to 4", async () => {
editor.innerText = "2+2";

parse(editor.innerText, output);
Expand All @@ -319,28 +356,28 @@ describe("testing parse", () => {
});

describe("testing postProcess", () => {
it("should return outputs when inputs and outputs lengths are equal", () => {
test("should return outputs when inputs and outputs lengths are equal", () => {
const inputs = ["2", "=", "3"];
const outputs = [2, "", 3];
const result = postProcess(inputs, outputs);
expect(result).toEqual([2, 2, 3]);
});

it("should return outputs adding previous inputs when inputs and outputs lengths are equal", () => {
test("should return outputs adding previous inputs when inputs and outputs lengths are equal", () => {
const inputs = ["2", "5", "total", "3"];
const outputs = [2, 5, "", 3];
const result = postProcess(inputs, outputs);
expect(result).toEqual([2, 5, 7, 3]);
});

it("should handle different lengths of inputs and outputs", () => {
test("should handle different lengths of inputs and outputs", () => {
const inputs = ["2", "sum", "3"];
const outputs = [2, 5];
const result = postProcess(inputs, outputs);
expect(result).toEqual([2, 5]);
});

it("should handle empty inputs", () => {
test("should handle empty inputs", () => {
const inputs = [];
const outputs = [2, 5];
const result = postProcess(inputs, outputs);
Expand All @@ -349,7 +386,7 @@ describe("testing postProcess", () => {
});

describe("Testing getResultTokens", () => {
it("should return a result token for a valid expression", () => {
test("should return a result token for a valid expression", () => {
const validExpression = "5 + 3";
const expectedResultToken = {
type: "result",
Expand All @@ -367,7 +404,7 @@ describe("Testing getResultTokens", () => {
expect(resultTokens).toEqual([expectedResultToken]);
});

it("should return an empty array for an empty expression", () => {
test("should return an empty array for an empty expression", () => {
const emptyExpression = "";

const resultTokens = getResultTokens([
Expand All @@ -381,7 +418,7 @@ describe("Testing getResultTokens", () => {
expect(resultTokens[0].value).toEqual("");
});

it("should return a null token for an invalid expression", () => {
test("should return a null token for an invalid expression", () => {
const invalidExpression = "invalid";
const expectedNullToken = {
type: "null",
Expand All @@ -399,7 +436,7 @@ describe("Testing getResultTokens", () => {
expect(resultTokens).toEqual([expectedNullToken]);
});

it("should return a null token for an expression with a null result", () => {
test("should return a null token for an expression with a null result", () => {
const nullExpression = "5 + null";
const expectedNullToken = {
type: "null",
Expand All @@ -417,7 +454,7 @@ describe("Testing getResultTokens", () => {
expect(resultTokens).toEqual([expectedNullToken]);
});

it("should return a null token for an expression with a NaN result", () => {
test("should return a null token for an expression with a NaN result", () => {
const nanExpression = "5 + NaN";
const expectedNullToken = {
type: "null",
Expand Down
8 changes: 4 additions & 4 deletions js/help_page.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createHelpTables } from "./help_page";
import { describe, it, expect } from "vitest";
import { describe, test, expect } from "vitest";
import path from "path";
import fs from "fs";

Expand All @@ -10,21 +10,21 @@ describe("createHelpTables tests", () => {

createHelpTables();

it("should create shortcut tables contents", () => {
test("should create shortcut tables contents", () => {
const shortcutTables = document.getElementById("shortcut-table-container");
expect(shortcutTables.querySelectorAll("td")[4].outerHTML).toEqual(
"<td>Open/Close help</td>"
);
});

it("should create operator tables contents", () => {
test("should create operator tables contents", () => {
const operatorTables = document.getElementById("operator-table-container");
expect(operatorTables.querySelectorAll("td")[2].outerHTML).toEqual(
"<td>2 + 3 = 5</td>"
);
});

it("should create unit tables contents", () => {
test("should create unit tables contents", () => {
const unitTables = document.getElementById("unit-table-container");
expect(unitTables.querySelectorAll("td")[5].outerHTML).toEqual(
"<td>m2, sqin, sqft, sqyd, sqmi, sqrd, sqch, sqmil, acre, hectare</td>"
Expand Down
6 changes: 3 additions & 3 deletions js/utils/convert_x_to_multiply.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { describe, it, expect } from "vitest";
import { describe, test, expect } from "vitest";
import { convertXToMultiplication } from "./convert_x_to_multiply";

describe("testing convertXToMultiplication", () => {
it("Convert all 'x' to multiplication operator", () => {
test("Convert all 'x' to multiplication operator", () => {
const lines = [
"2x3",
"2 x 3",
Expand All @@ -25,7 +25,7 @@ describe("testing convertXToMultiplication", () => {
]);
});

it("Dont convert some 'x' to multiplication operator in expressions", () => {
test("Dont convert some 'x' to multiplication operator in expressions", () => {
const lines = ["2xdata", "0x90 x 2", "0x90x 2", "x22e x2x4x1.7x0.41"];
const convertedLines = convertXToMultiplication(lines);

Expand Down

0 comments on commit 58d7167

Please sign in to comment.