Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,18 @@ return "yes";`;
action: "Delete",
entityType: entityItems.JSObject,
});
it("11. Should throw an error when JS Object is empty", () => {
const jsObjectEmptyToastMessage =
"JS object must contain 'export default'.";
jsEditor.CreateJSObject(` `, {
paste: true,
completeReplace: true,
toRun: false,
prettify: false,
});

agHelper.AssertContains(jsObjectEmptyToastMessage);
});
});
},
);
4 changes: 4 additions & 0 deletions app/client/src/ce/constants/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2505,6 +2505,10 @@ export const EMPTY_DATASOURCE_TOOLTIP_SIDEBUTTON = () =>
"Create a datasource to power your app with data.";

export const FIELD_REQUIRED_MESSAGE = () => `This field is required`;
export const EMPTY_JS_OBJECT_ERROR_MESSAGE = () =>
"JS object must contain 'export default'.";
export const JS_OBJECT_DEFAULT_EXPORT_ERROR_MESSAGE = () =>
"Start object with export default";

export const PREPARED_STATEMENT_WARNING = {
MESSAGE: () =>
Expand Down
10 changes: 8 additions & 2 deletions app/client/src/sagas/EvalErrorHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,17 @@ export function* evalErrorHandler(
break;
}
case EvalErrorTypes.PARSE_JS_ERROR: {
toast.show(`${error.message} at: ${error.context?.entity.name}`, {
let errorMessage = error.message;

if (!!error.context) {
errorMessage = `${error.message}`;
}

toast.show(errorMessage, {
Comment on lines +290 to +296

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Class, let's examine the changes in our error handling.

Now, students, I want you to pay close attention to how we've simplified our error message construction. This is a good step towards clarity, but we have a small issue to address.

  1. The simplification of the error message is commendable. We've removed the entity name from the context, focusing solely on the error message itself. This can make the error more concise and easier to understand.

  2. However, we have a little redundancy in our code. Can anyone spot it? Yes, you in the back! That's right, the double negation in the condition !!error.context is unnecessary. Remember, class, JavaScript will automatically coerce the value to a boolean in an if statement. Let's clean that up.

  3. Lastly, notice how we're now using the same error message for both the toast notification and the console log. Consistency is key in error reporting, children!

Let's make a small correction to improve our code:

-if (!!error.context) {
+if (error.context) {
  errorMessage = `${error.message}`;
}

This change will make our code cleaner and easier to read. Remember, class, always strive for clarity and simplicity in your code!

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let errorMessage = error.message;
if (!!error.context) {
errorMessage = `${error.message}`;
}
toast.show(errorMessage, {
let errorMessage = error.message;
if (error.context) {
errorMessage = `${error.message}`;
}
toast.show(errorMessage, {
🧰 Tools
🪛 Biome

[error] 292-292: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

kind: "error",
});
AppsmithConsole.error({
text: `${error.message} at: ${error.context?.propertyPath}`,
text: `${error.message}`,
});
break;
}
Expand Down
39 changes: 29 additions & 10 deletions app/client/src/workers/Evaluation/JSObject/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import JSObjectCollection from "./Collection";
import ExecutionMetaData from "../fns/utils/ExecutionMetaData";
import { jsPropertiesState } from "./jsPropertiesState";
import { getFixedTimeDifference } from "workers/common/DataTreeEvaluator/utils";
import {
createMessage,
EMPTY_JS_OBJECT_ERROR_MESSAGE,
JS_OBJECT_DEFAULT_EXPORT_ERROR_MESSAGE,
} from "ee/constants/messages";

/**
* Here we update our unEvalTree according to the change in JSObject's body
Expand Down Expand Up @@ -228,16 +233,30 @@ export function saveResolvedFunctionsAndJSUpdates(
}

if (!correctFormat && !isUndefined(entity.body)) {
const errors = {
type: EvalErrorTypes.PARSE_JS_ERROR,
context: {
entity: entity,
propertyPath: entityName + ".body",
},
message: "Start object with export default",
};

dataTreeEvalRef.errors.push(errors);
if (entity.body.trim() !== "") {
const errors = {
type: EvalErrorTypes.PARSE_JS_ERROR,
context: {
entity: entity,
propertyPath: entityName + ".body",
},
message: createMessage(JS_OBJECT_DEFAULT_EXPORT_ERROR_MESSAGE),
};

dataTreeEvalRef.errors.push(errors);
} else {
const errors = {
type: EvalErrorTypes.PARSE_JS_ERROR,
context: {
entity: entity,
propertyPath: entityName,
},
message: createMessage(EMPTY_JS_OBJECT_ERROR_MESSAGE),
show: false,
};

dataTreeEvalRef.errors.push(errors);
}
}

return jsUpdates;
Expand Down
48 changes: 47 additions & 1 deletion app/client/src/workers/Evaluation/JSObject/test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import type { ConfigTree, UnEvalTree } from "entities/DataTree/dataTreeTypes";
import { getUpdatedLocalUnEvalTreeAfterJSUpdates } from ".";
import {
getUpdatedLocalUnEvalTreeAfterJSUpdates,
saveResolvedFunctionsAndJSUpdates,
} from ".";

describe("updateJSCollectionInUnEvalTree", function () {
it("updates async value of jsAction", () => {
Expand Down Expand Up @@ -136,4 +139,47 @@ describe("updateJSCollectionInUnEvalTree", function () {

expect(expectedResult).toStrictEqual(actualResult);
});
it("should raise empty toast message when JSObject is empty", () => {
const mockFunction = jest.fn();

saveResolvedFunctionsAndJSUpdates(
{ errors: { push: mockFunction } },
{ body: " " },
{},
{},
"JSObject1",
);

expect(mockFunction).toBeCalled;
expect(mockFunction).toHaveBeenCalledWith({
type: "PARSE_JS_ERROR",
context: {
entity: { body: " " },
propertyPath: "JSObject1",
},
message: "JS object must contain 'export default'.",
show: false,
});
});
it("should raise appropriate toast message based on JSObject body content", () => {
const mockFunction = jest.fn();

saveResolvedFunctionsAndJSUpdates(
{ errors: { push: mockFunction } },
{ body: "export" },
{},
{},
"JSObject1",
);

expect(mockFunction).toBeCalled();
expect(mockFunction).toHaveBeenCalledWith({
type: "PARSE_JS_ERROR",
context: {
entity: { body: "export" },
propertyPath: "JSObject1.body",
},
message: "Start object with export default",
});
});
});