Repository: splunk/addonfactory-ucc-generator (language: python)

Issue:
fix: display newest information in row more info section
**Issue number:** *ADDON-76309*

Closes #1410.

## Summary

### Changes

> More info data is getting updated when the row is expanded

### User experience

> User can update the row details and check the updated data will render when the row is expanded.

## Checklist

If your change doesn't seem to apply, please leave them unchecked.

* [X] I have performed a self-review of this change
* [X] Changes have been tested
* [ ] Changes are documented
* [X] PR title follows [conventional commit semantics](https://www.conventionalcommits.org/en/v1.0.0/)



Discussion / hints:
do you think it is feasible to add the test to reproduce the bug, then fix it and fix the test?
> do you think it is feasible to add the test to reproduce the bug, then fix it and fix the test?

yeah sure, will add the test case first that will cover the bug and fix them
since you already checked most of the file maybe worth moving to typescript or even convert to functional component for consistency (most of components are made that way), wdyt?

or maybe better to do it in separate PR

Fix patch:
diff --git a/ui/src/components/table/stories/configMockups.ts b/ui/src/components/table/stories/configMockups.ts
index f92c8a354..507032372 100644
--- a/ui/src/components/table/stories/configMockups.ts
+++ b/ui/src/components/table/stories/configMockups.ts
@@ -113,7 +113,7 @@ export const SIMPLE_NAME_TABLE_MOCK_DATA = {
 
 export const getSimpleConfig = () => {
     const configCp = JSON.parse(JSON.stringify(SIMPLE_NAME_TABLE_MOCK_DATA));
-    return configCp;
+    return configCp as GlobalConfig;
 };
 
 export const TABLE_CONFIG_WITH_MAPPING = {


Test patch:
diff --git a/ui/src/components/table/tests/TableExpansionRow.test.tsx b/ui/src/components/table/tests/TableExpansionRow.test.tsx
new file mode 100644
index 000000000..9fdd0ca94
--- /dev/null
+++ b/ui/src/components/table/tests/TableExpansionRow.test.tsx
@@ -0,0 +1,172 @@
+import { render, screen, waitFor, waitForElementToBeRemoved, within } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import React from 'react';
+import { http, HttpResponse } from 'msw';
+import { BrowserRouter } from 'react-router-dom';
+import TableWrapper, { ITableWrapperProps } from '../TableWrapper';
+import { server } from '../../../mocks/server';
+import { TableContextProvider } from '../../../context/TableContext';
+import { setUnifiedConfig } from '../../../util/util';
+import { getSimpleConfig } from '../stories/configMockups';
+import { getMockServerResponseForInput } from '../../../mocks/server-response';
+import { GlobalConfig } from '../../../types/globalConfig/globalConfig';
+import { getBuildDirPath } from '../../../util/script';
+import mockCustomInputRow from '../../../../../tests/testdata/test_addons/package_global_config_everything/package/appserver/static/js/build/custom/custom_input_row';
+
+const inputName = 'example_input_one';
+const interval = 7766;
+const updatedInterval = 7788;
+
+const props = {
+    page: 'inputs',
+    serviceName: inputName,
+    handleRequestModalOpen: jest.fn(),
+    handleOpenPageStyleDialog: jest.fn(),
+} satisfies ITableWrapperProps;
+
+const baseConfig = getSimpleConfig();
+const customRowFileName = 'CustomInputRow';
+
+function setup() {
+    jest.mock(`${getBuildDirPath()}/custom/${customRowFileName}.js`, () => mockCustomInputRow, {
+        virtual: true,
+    });
+
+    const headers = [
+        {
+            label: 'Name',
+            field: 'name',
+        },
+        {
+            label: 'Interval',
+            field: 'interval',
+        },
+    ];
+    setUnifiedConfig({
+        ...baseConfig,
+        pages: {
+            ...baseConfig.pages,
+            inputs: {
+                title: inputName,
+                services: [
+                    {
+                        title: inputName,
+                        name: inputName,
+                        entity: [
+                            {
+                                label: 'Name',
+                                field: 'name',
+                                type: 'text',
+                            },
+                            {
+                                label: 'Interval',
+                                field: 'interval',
+                                type: 'text',
+                            },
+                        ],
+                    },
+                ],
+                table: {
+                    actions: ['edit'],
+                    header: headers,
+                    moreInfo: headers,
+                    customRow: {
+                        src: customRowFileName,
+                        type: 'external',
+                    },
+                },
+            },
+        },
+    } satisfies GlobalConfig);
+
+    server.use(
+        http.get(`/servicesNS/nobody/-/splunk_ta_uccexample_${inputName}`, () =>
+            HttpResponse.json(
+                getMockServerResponseForInput([
+                    {
+                        name: inputName,
+                        content: {
+                            interval,
+                        },
+                    },
+                ])
+            )
+        )
+    );
+
+    render(
+        <TableContextProvider>
+            <TableWrapper {...props} />
+        </TableContextProvider>,
+        { wrapper: BrowserRouter }
+    );
+}
+
+async function expectIntervalInExpandedRow(inputRow: HTMLElement, expectedInterval: number) {
+    const arrow = within(inputRow).getByRole('cell', { name: /expandable/i });
+    const isExpanded = arrow.getAttribute('aria-expanded');
+    if (isExpanded === 'false') {
+        await userEvent.click(arrow);
+    }
+    await waitFor(() => expect(arrow.getAttribute('aria-expanded')).not.toBe('false'));
+    const loading = screen.queryByText('Loading...');
+    if (loading) {
+        await waitForElementToBeRemoved(loading);
+    }
+
+    const allDefinitions = screen.getAllByRole('definition').map((el) => el.textContent);
+
+    expect(allDefinitions).toContain(`${expectedInterval} sec`);
+}
+
+it.failing('should update custom Expansion Row when Input has changed', async () => {
+    setup();
+    const inputRow = await screen.findByRole('row', { name: `row-${inputName}` });
+
+    // simulate the server response for the post request
+    server.use(
+        http.post(
+            `/servicesNS/nobody/-/splunk_ta_uccexample_${inputName}/${inputName}`,
+            async ({ request }) => {
+                const formData = await request.formData();
+                const formDataObject: Record<string, string> = {};
+                formData.forEach((value, key) => {
+                    if (typeof value === 'string') {
+                        formDataObject[key] = value;
+                    }
+                });
+                return HttpResponse.json(
+                    getMockServerResponseForInput([
+                        {
+                            name: inputName,
+                            content: formDataObject,
+                        },
+                    ])
+                );
+            }
+        )
+    );
+
+    await expectIntervalInExpandedRow(
+        await screen.findByRole('row', { name: `row-${inputName}` }),
+        interval
+    );
+
+    await userEvent.click(within(inputRow).getByRole('button', { name: /edit/i }));
+    const dialog = await screen.findByRole('dialog');
+
+    const textBoxes = within(dialog).getAllByRole('textbox');
+    expect(textBoxes).toHaveLength(2);
+    const intervalInput = textBoxes[1];
+    expect(intervalInput).toHaveValue(interval.toString());
+    await userEvent.clear(intervalInput);
+    await userEvent.type(intervalInput, updatedInterval.toString());
+    await userEvent.click(screen.getByRole('button', { name: /update/i }));
+
+    await screen.findByRole('cell', { name: updatedInterval.toString() });
+
+    await expectIntervalInExpandedRow(
+        await screen.findByRole('row', { name: `row-${inputName}` }),
+        updatedInterval
+    );
+});