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
2 changes: 2 additions & 0 deletions app/client/cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export default defineConfig({
responseTimeout: 60000,
pageLoadTimeout: 60000,
video: true,
videosFolder: "cypress/videos",
Copy link
Contributor

Choose a reason for hiding this comment

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

The video setting is already enabled, which means that Cypress will record videos of our tests. The videosFolder setting is also not necessary, as the default location for video recordings is cypress/videos.
Regarding the videoCompression setting, it's generally recommended to keep the default value of false unless you have specific requirements for video quality. Setting it to 32 can impact the performance of our tests, as the video compression process can slow down the test runtime.

videoCompression: 32,
numTestsKeptInMemory: 5,
experimentalMemoryManagement: true,
reporterOptions: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import widgetLocators from "../../../../locators/Widgets.json";
import template from "../../../../locators/TemplatesLocators.json";
import {
agHelper,
locators,
templates,
} from "../../../../support/Objects/ObjectsCore";
import EditorNavigation, {
EntityType,
} from "../../../../support/Pages/EditorNavigation";
import PageList from "../../../../support/Pages/PageList";

beforeEach(() => {
cy.get("body").then(($ele) => {
if ($ele.find(template.templateDialogBox).length) {
cy.xpath(template.closeButton).click({ force: true });
}
});
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
});

describe(
"Fork a template to the current aplication using Redux store",
{ tags: ["@tag.Templates", "@tag.excludeForAirgap"] },
() => {
it("Fork template from page section", () => {

PageList.AddNewPage("Add page from template");
agHelper.AssertElementExist(template.templateDialogBox);
agHelper.AssertElementVisibility(template.templateDialogBox);
agHelper.AssertElementVisibility(templates.locators._templateCard);
agHelper.AssertElementVisibility(template.vehicleMaintenenceApp);
agHelper.GetNClick(template.vehicleMaintenenceApp);

agHelper.AssertElementAbsence(
"//*[text()='Loading template details']",
Cypress.config().pageLoadTimeout,
);

agHelper.FailIfErrorToast(
"Internal server error while processing request",
);

cy.get("body").then(($ele) => {
if ($ele.find(widgetLocators.toastAction).length <= 0) {
if ($ele.find(template.templateViewForkButton).length > 0) {
cy.get(template.templateViewForkButton).click();
}
}
});


agHelper.AssertElementAbsence(
locators._visibleTextSpan("Setting up the template"),
Cypress.config().pageLoadTimeout,
);


agHelper.ValidateToastMessage("template added successfully");
agHelper.AssertElementVisibility(locators._itemContainerWidget);
agHelper.WaitUntilAllToastsDisappear();

const vehicleMaintenenceAppTemplateId=defaultAppState.ui.templates.templates[4].id
const endpoint = `/api/v1/app-templates/${vehicleMaintenenceAppTemplateId}`;
cy.intercept('GET', endpoint).as('fetchTemplateDetails');
cy.get('@fetchTemplateDetails.all').should('have.length', 0);
});
},
);
31 changes: 24 additions & 7 deletions app/client/src/api/TemplatesApi.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to suggest a different approach to solving this problem.
Instead of directly accessing the API and checking the local state, I would recommend identifying the root cause of the redundant API call. This could involve tracing the code path that leads to the API call and understanding why it's being made in the first place and preventing it.
By addressing the root cause, you can ensure that the fix is more robust and less prone to unintended consequences. Additionally, this approach will help us better understand the code and make more informed decisions about how to improve it.
In this specific case, making changes to the TemplateApi could have unintended effects on other parts of the application. It's better to focus on the specific code path that's causing the redundant API call and fix it at that level.
If you're willing, I'd be happy to help you investigate the root cause of the API call and find a more targeted solution.
Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @jacquesikot , Thanks for your suugestion , i will try to find the root cause for this additional API call.

Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import type { AxiosPromise } from "axios";
import Api from "api/Api";
import type { ApiResponse } from "./ApiResponses";
import type { WidgetType } from "constants/WidgetConstants";
import type {
ApplicationResponsePayload,
ApplicationPagePayload,
ApplicationResponsePayload,
} from "@appsmith/api/ApplicationApi";
import Api from "api/Api";
import type { AxiosPromise } from "axios";
import type { WidgetType } from "constants/WidgetConstants";
import type { Datasource } from "entities/Datasource";
import { getTemplatesSelector } from "selectors/templatesSelectors";
import store from "store";
import type { ApiResponse } from "./ApiResponses";

export interface Template {
id: string;
Expand All @@ -27,6 +29,8 @@ export interface Template {
}

export type FetchTemplatesResponse = ApiResponse<Template[]>;
export type TemplatesResponse = Template;

export type FilterKeys = "widgets" | "datasources";

export type FetchTemplateResponse = ApiResponse<Template>;
Expand Down Expand Up @@ -62,6 +66,12 @@ export type PublishCommunityTemplateResponse = ApiResponse<{
modifiedAt: string;
}>;

const createTemplateResponse = (data: Template) => ({
responseMeta: { status: 200, success: true },
data,
errorDisplay: "",
});

class TemplatesAPI extends Api {
static baseUrl = "v1";

Expand All @@ -72,9 +82,16 @@ class TemplatesAPI extends Api {
}
static async getTemplateInformation(
templateId: string,
): Promise<AxiosPromise<FetchTemplatesResponse>> {
): Promise<AxiosPromise<TemplatesResponse>> {
const state = store.getState();
const templates = getTemplatesSelector(state);
const template = templates.find((template) => template.id === templateId);
if (template) {
return createTemplateResponse(template) as AxiosPromise<TemplatesResponse>;
}
Comment on lines +85 to +91
Copy link
Contributor

Choose a reason for hiding this comment

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

Tip

Codebase Verification

Ensure proper error handling in getTemplateInformation.

The getTemplateInformation function currently lacks proper error handling mechanisms. Specifically, it does not handle the scenario where the template is not found in the Redux store or if the API call fails.

  • Add error handling for the case when the template is not found in the Redux store.
  • Add error handling for potential failures in the API call.
Analysis chain

Ensure proper error handling in getTemplateInformation.

While the function now fetches templates from the Redux store, it's crucial to ensure that error scenarios are handled appropriately, especially when the template is not found in the store.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify proper error handling when fetching templates.

# Test: Search for error handling patterns in the TemplatesApi.ts file. Expect: Proper error handling mechanisms.
rg --type ts 'catch|throw|error' app/client/src/api/TemplatesApi.ts

Length of output: 92



Script:

#!/bin/bash
# Description: Locate and inspect the getTemplateInformation function in TemplatesApi.ts for error handling.

# Locate the getTemplateInformation function
ast-grep --lang typescript --pattern 'function getTemplateInformation($_, $_) { $$$ }' app/client/src/api/TemplatesApi.ts

Length of output: 123



Script:

#!/bin/bash
# Description: Search for the getTemplateInformation function by name in TemplatesApi.ts.

# Search for the getTemplateInformation function
rg 'getTemplateInformation' app/client/src/api/TemplatesApi.ts

Length of output: 101



Script:

#!/bin/bash
# Description: Extract the full implementation of the getTemplateInformation function from TemplatesApi.ts.

# Extract the full implementation of the getTemplateInformation function
ast-grep --lang typescript --pattern 'static async getTemplateInformation($_, $_) { $$$ }' app/client/src/api/TemplatesApi.ts

Length of output: 601



Script:

#!/bin/bash
# Description: Extract the full implementation of the getTemplateInformation function from TemplatesApi.ts.

# Corrected pattern to extract the full implementation of the getTemplateInformation function
ast-grep --lang typescript --pattern 'class $_ { static async getTemplateInformation($_, $_) { $$$ } }' app/client/src/api/TemplatesApi.ts

Length of output: 140



Script:

#!/bin/bash
# Description: Search for the getTemplateInformation function definition and surrounding lines in TemplatesApi.ts.

# Search for the getTemplateInformation function definition and surrounding lines
rg -A 20 'static async getTemplateInformation' app/client/src/api/TemplatesApi.ts

Length of output: 815

return Api.get(TemplatesAPI.baseUrl + `/app-templates/${templateId}`);
}

static async getSimilarTemplates(
templateId: string,
): Promise<AxiosPromise<FetchTemplatesResponse>> {
Expand Down Expand Up @@ -118,4 +135,4 @@ class TemplatesAPI extends Api {
}
}

export default TemplatesAPI;
export default TemplatesAPI;