Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: copy paste last value pasting a promise #26

Merged
merged 3 commits into from
Jun 21, 2024
Merged
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
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
Loading