Skip to content

Commit

Permalink
Merge branch 'main' into task/WP-72--highlight-matching-search-terms
Browse files Browse the repository at this point in the history
  • Loading branch information
shayanaijaz authored Oct 24, 2023
2 parents 6b24fb0 + fa8c979 commit fe264b9
Show file tree
Hide file tree
Showing 33 changed files with 653 additions and 265 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [3.2.1] - 2023-10-05: Search and Target Path fixes

### Fixed
WP-297: Fix site search for public and community data (#870)
WP-306: Fix target path regression (#871)

## [3.2.0] - 2023-10-02: V3 integration improvements; bug fixes

### Added
Expand Down Expand Up @@ -953,7 +959,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.0.0] - 2020-02-28
v1.0.0 Production release as of Feb 28, 2020.

[unreleased]: https://github.com/TACC/Core-Portal/compare/v3.1.2...HEAD
[unreleased]: https://github.com/TACC/Core-Portal/compare/v3.2.1...HEAD
[3.2.1]: https://github.com/TACC/Core-Portal/releases/tag/v3.2.1
[3.2.0]: https://github.com/TACC/Core-Portal/releases/tag/v3.2.0
[3.1.2]: https://github.com/TACC/Core-Portal/releases/tag/v3.1.2
[3.1.1]: https://github.com/TACC/Core-Portal/releases/tag/v3.1.1
Expand Down
309 changes: 163 additions & 146 deletions client/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"stylelint": "^14.4.0",
"stylelint-config-recommended": "^7.0.0",
"stylelint-config-standard": "^25.0.0",
"timekeeper": "^2.3.1",
"typescript": "^4.4.3",
"vite": "^2.9.16",
"weak-key": "^1.0.1"
Expand Down
32 changes: 23 additions & 9 deletions client/src/components/Applications/AppForm/AppForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Link } from 'react-router-dom';
import { getSystemName } from 'utils/systems';
import FormSchema from './AppFormSchema';
import {
checkAndSetDefaultTargetPath,
isTargetPathEmpty,
isTargetPathField,
getInputFieldFromTargetPathField,
getQueueMaxMinutes,
Expand Down Expand Up @@ -484,6 +484,7 @@ export const AppSchemaForm = ({ app }) => {
targetDir: isTargetPathField(k) ? v : null,
};
})
.filter((v) => v) //filter nulls
.reduce((acc, entry) => {
// merge input field and targetPath fields into one.
const key = getInputFieldFromTargetPathField(entry.name);
Expand All @@ -501,9 +502,12 @@ export const AppSchemaForm = ({ app }) => {
.flat()
.filter((fileInput) => fileInput.sourceUrl) // filter out any empty values
.map((fileInput) => {
fileInput.targetPath = checkAndSetDefaultTargetPath(
fileInput.targetPath
);
if (isTargetPathEmpty(fileInput.targetPath)) {
return {
name: fileInput.name,
sourceUrl: fileInput.sourceUrl,
};
}
return fileInput;
});

Expand Down Expand Up @@ -688,11 +692,21 @@ export const AppSchemaForm = ({ app }) => {
)
.map((q) => q.name)
.sort()
.map((queueName) => (
<option key={queueName} value={queueName}>
{queueName}
</option>
))
.map((queueName) =>
app.definition.notes.queueFilter ? (
app.definition.notes.queueFilter.includes(
queueName
) && (
<option key={queueName} value={queueName}>
{queueName}
</option>
)
) : (
<option key={queueName} value={queueName}>
{queueName}
</option>
)
)
.sort()}
</FormField>
)}
Expand Down
226 changes: 224 additions & 2 deletions client/src/components/Applications/AppForm/AppForm.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import { fireEvent, render, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import { BrowserRouter } from 'react-router-dom';
Expand All @@ -15,11 +16,16 @@ import {
appTrayExpectedFixture,
} from '../../../redux/sagas/fixtures/apptray.fixture';
import { initialAppState } from '../../../redux/reducers/apps.reducers';
import { helloWorldAppFixture } from './fixtures/AppForm.app.fixture';
import {
helloWorldAppFixture,
helloWorldAppSubmissionPayloadFixture,
} from './fixtures/AppForm.app.fixture';
import systemsFixture from '../../DataFiles/fixtures/DataFiles.systems.fixture';
import { projectsFixture } from '../../../redux/sagas/fixtures/projects.fixture';
import '@testing-library/jest-dom/extend-expect';
import timekeeper from 'timekeeper';

const frozenDate = '2023-10-01';
const mockStore = configureStore();
const initialMockState = {
allocations: allocationsFixture,
Expand Down Expand Up @@ -56,6 +62,11 @@ function renderAppSchemaFormComponent(store, app) {
}

describe('AppSchemaForm', () => {
beforeAll(() => {
// Lock Time
timekeeper.freeze(new Date(frozenDate));
});

it('renders the AppSchemaForm', async () => {
const store = mockStore({
...initialMockState,
Expand Down Expand Up @@ -257,6 +268,162 @@ describe('AppSchemaForm', () => {
expect(getByText(/Activate your Application Name license/)).toBeDefined();
});
});

it('job submission with file input mode FIXED', async () => {
const store = mockStore({
...initialMockState,
});

const { getByText, container } = renderAppSchemaFormComponent(store, {
...helloWorldAppFixture,
definition: {
...helloWorldAppFixture.definition,
jobAttributes: {
...helloWorldAppFixture.definition.jobAttributes,
fileInputs: [
{
name: 'File to copy',
description: 'A fixed file used by the app',
inputMode: 'FIXED',
autoMountLocal: true,
sourceUrl:
'tapis://corral-tacc/tacc/aci/secure-test/rallyGolf.jpg',
targetPath: 'rallyGolf.jpg',
},
],
},
},
});
const hiddenFileInput = container.querySelector(
'input[name="fileInputs.File to copy"]'
);
// FIXED fields are still shown in UI but not submitted.
expect(hiddenFileInput).toBeInTheDocument();

const submitButton = getByText(/Submit/);
fireEvent.click(submitButton);
const payload = {
...helloWorldAppSubmissionPayloadFixture,
job: {
...helloWorldAppSubmissionPayloadFixture.job,
name: 'hello-world-0.0.1_' + frozenDate + 'T00:00:00',
},
};

await waitFor(() => {
expect(store.getActions()).toEqual([
{ type: 'GET_SYSTEM_MONITOR' },
{ type: 'SUBMIT_JOB', payload: payload },
]);
});
});

it('job submission with file input hidden', async () => {
const store = mockStore({
...initialMockState,
});

const { getByText, container } = renderAppSchemaFormComponent(store, {
...helloWorldAppFixture,
definition: {
...helloWorldAppFixture.definition,
jobAttributes: {
...helloWorldAppFixture.definition.jobAttributes,
fileInputs: [
{
name: 'File to copy',
description: 'A fixed file used by the app',
inputMode: 'REQUIRED',
autoMountLocal: true,
sourceUrl:
'tapis://corral-tacc/tacc/aci/secure-test/rallyGolf.jpg',
targetPath: 'rallyGolf.jpg',
notes: {
isHidden: true,
},
},
],
},
},
});

const hiddenFileInput = container.querySelector(
'input[name="fileInputs.File to copy"]'
);
expect(hiddenFileInput).not.toBeInTheDocument();

const submitButton = getByText(/Submit/);
fireEvent.click(submitButton);
const payload = {
...helloWorldAppSubmissionPayloadFixture,
job: {
...helloWorldAppSubmissionPayloadFixture.job,
name: 'hello-world-0.0.1_' + frozenDate + 'T00:00:00',
},
};

await waitFor(() => {
expect(store.getActions()).toEqual([
{ type: 'GET_SYSTEM_MONITOR' },
{ type: 'SUBMIT_JOB', payload: payload },
]);
});
});

it('job submission with custom target path', async () => {
const store = mockStore({
...initialMockState,
});
const { getByText, container } = renderAppSchemaFormComponent(store, {
...helloWorldAppFixture,
definition: {
...helloWorldAppFixture.definition,
notes: {
...helloWorldAppFixture.definition.notes,
showTargetPath: true,
},
},
});

const fileInput = container.querySelector(
'input[name="fileInputs.File to modify"]'
);
const file = 'tapis://foo/bar.txt';
const targetPathForFile = 'baz.txt';
fireEvent.change(fileInput, { target: { value: file } });
const targetPathInput = container.querySelector(
'input[name="fileInputs._TargetPath_File to modify"]'
);
fireEvent.change(targetPathInput, { target: { value: targetPathForFile } });

const submitButton = getByText(/Submit/);
fireEvent.click(submitButton);
const payload = {
...helloWorldAppSubmissionPayloadFixture,
job: {
...helloWorldAppSubmissionPayloadFixture.job,
fileInputs: [
{
name: 'File to modify',
sourceUrl: file,
targetPath: targetPathForFile,
},
],
name: 'hello-world-0.0.1_' + frozenDate + 'T00:00:00',
},
};

await waitFor(() => {
expect(store.getActions()).toEqual([
{ type: 'GET_SYSTEM_MONITOR' },
{ type: 'SUBMIT_JOB', payload: payload },
]);
});
});

afterAll(() => {
timekeeper.reset();
});
});

describe('AppDetail', () => {
Expand All @@ -275,3 +442,58 @@ describe('AppDetail', () => {
).toBeDefined();
});
});

const mockAppWithQueueFilter = {
...helloWorldAppFixture,
definition: {
...helloWorldAppFixture.definition,
notes: {
...helloWorldAppFixture.definition.notes,
queueFilter: ['rtx', 'small'],
},
},
};

const mockAppWithoutQueueFilter = {
...helloWorldAppFixture,
definition: {
...helloWorldAppFixture.definition,
notes: {
...helloWorldAppFixture.definition.notes,
queueFilter: null,
},
},
};

describe('AppSchemaForm queueFilter tests', () => {
it('renders only the queues specified in the queueFilter', () => {
const { container } = renderAppSchemaFormComponent(
mockStore(initialMockState),
mockAppWithQueueFilter
);

const targetDropdown = container.querySelector(
'select[name="execSystemLogicalQueue"]'
);
const options = Array.from(targetDropdown.querySelectorAll('option'));
expect(options).toHaveLength(2);
expect(options[0].textContent).toBe('rtx');
expect(options[1].textContent).toBe('small');
});

it('renders all queues when no queueFilter is present', () => {
const { container } = renderAppSchemaFormComponent(
mockStore(initialMockState),
mockAppWithoutQueueFilter
);

const targetDropdown = container.querySelector(
'select[name="execSystemLogicalQueue"]'
);
const options = Array.from(targetDropdown.querySelectorAll('option'));
expect(options).toHaveLength(3);
expect(options[0].textContent).toBe('development');
expect(options[1].textContent).toBe('rtx');
expect(options[2].textContent).toBe('small');
});
});
9 changes: 4 additions & 5 deletions client/src/components/Applications/AppForm/AppFormSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,10 @@ const FormSchema = (app) => {
app.definition.notes.showTargetPath ?? false;
(app.definition.jobAttributes.fileInputs || []).forEach((i) => {
const input = i;
/* TODOv3 consider hidden file inputs https://jira.tacc.utexas.edu/browse/WP-102
if (input.name.startsWith('_') || !input.value.visible) { // TODOv3 visible or hidden
return;
}
*/
if (input.notes?.isHidden) {
return;
}

const field = {
label: input.name,
description: input.description,
Expand Down
Loading

0 comments on commit fe264b9

Please sign in to comment.