Skip to content

Commit

Permalink
console debug log level (#190)
Browse files Browse the repository at this point in the history
* adding debug level selection

* adding debug logger level functionality, added test and modify impacted tests

* adding unit test for checking debug when running sushi

---------

Co-authored-by: Chris Moesel <cmoesel@users.noreply.github.com>
  • Loading branch information
KaelynJefferson and cmoesel authored Oct 28, 2024
1 parent e172742 commit b9a4685
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 19 deletions.
7 changes: 7 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export default function App(props) {
const [configToShare, setConfigToShare] = useState({ canonical: '', version: '', fhirVersion: [], dependencies: '' });
const [sharedConfig, setSharedConfig] = useState({});
const [isLineWrapped, setIsLineWrapped] = useState(false);
const [isDebugConsoleChecked, setIsDebugConsoleChecked] = useState(false);

useEffect(() => {
async function waitForFSH() {
Expand Down Expand Up @@ -267,6 +268,10 @@ export default function App(props) {
setIsLineWrapped(wrapSelected);
}

function setDebugConsoleChecked(debugSelected) {
setIsDebugConsoleChecked(debugSelected);
}

function debouncedMove(clientX) {
if (isDragging) {
const newPercentage = (clientX / window.innerWidth) * 100;
Expand Down Expand Up @@ -365,6 +370,8 @@ export default function App(props) {
saveAll={saveAll}
setIsLineWrapped={setLineWrap}
isLineWrapped={isLineWrapped}
setIsDebugConsoleChecked={setDebugConsoleChecked}
isDebugConsoleChecked={isDebugConsoleChecked}
/>
</div>
<div className={expandConsole ? classes.collapsedMain : classes.expandedMain}>
Expand Down
22 changes: 20 additions & 2 deletions src/components/FSHControls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ export default function FSHControls(props) {
props.setIsLineWrapped(isLineWrappedChecked);
};

const updateConsoleMessageLevel = (event) => {
const isDebugConsoleChecked = event.target.checked;
props.setIsDebugConsoleChecked(isDebugConsoleChecked);
};

async function handleSUSHIClick() {
if (props.isWaiting) {
// If SUSHI or GoFSH is in the middle of processes, don't do anything
Expand All @@ -193,7 +198,12 @@ export default function FSHControls(props) {
FSHOnly: true,
fhirVersion: fhirVersion ? [fhirVersion] : ['4.0.1']
};
const outPackage = await runSUSHI(props.fshText, config, parsedDependencies);
const outPackage = await runSUSHI(
props.fshText,
config,
parsedDependencies,
props.isDebugConsoleChecked ? 'debug' : 'info'
);
let jsonOutput = JSON.stringify(outPackage, replacer, 2);
if (outPackage && outPackage.codeSystems) {
if (
Expand Down Expand Up @@ -239,7 +249,7 @@ export default function FSHControls(props) {
}

const options = { dependencies: parsedDependencies, indent: isGoFSHIndented };
const { fsh, config } = await runGoFSH(gofshInputStrings, options);
const { fsh, config } = await runGoFSH(gofshInputStrings, options, props.isDebugConsoleChecked ? 'debug' : 'info');
props.onGoFSHClick(fsh, false);
setIsGoFSHRunning(false);
if (canonical === '' && config.canonical) setCanonical(config.canonical);
Expand Down Expand Up @@ -401,6 +411,14 @@ export default function FSHControls(props) {
onChange={updateLineWrapping}
/>
<FormHelperText>If set, FSH Online will display code with line wrapping</FormHelperText>
<FormControlLabel
id="debugLevelConsole"
margin="dense"
control={<Checkbox checked={props.isDebugConsoleChecked} color="primary" />}
label="Debug level console messages"
onChange={updateConsoleMessageLevel}
/>
<FormHelperText>If set, FSH Online will display debug level messages within the console</FormHelperText>
</DialogContent>
<DialogActions>
<Button onClick={handleCloseConfig} color="primary">
Expand Down
8 changes: 4 additions & 4 deletions src/utils/FSHHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ const FHIRDefinitions = fhirdefs.FHIRDefinitions;
* indent: user set, defaults to false
* @returns {string} the FSH
*/
export async function runGoFSH(input, options) {
export async function runGoFSH(input, options, loggerLevel) {
gofshStats.reset();
setCurrentLogger('gofsh');
setCurrentLogger('gofsh', loggerLevel);

// Read in the resources as strings
const docs = [];
Expand Down Expand Up @@ -92,9 +92,9 @@ export async function runGoFSH(input, options) {
*
* @returns Package with FHIR resources
*/
export async function runSUSHI(input, config, dependencies = []) {
export async function runSUSHI(input, config, dependencies = [], loggerLevel) {
sushiStats.reset();
setCurrentLogger('sushi');
setCurrentLogger('sushi', loggerLevel);

// Load dependencies
let defs = new FHIRDefinitions();
Expand Down
3 changes: 2 additions & 1 deletion src/utils/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { utils as gofshUtils } from 'gofsh';
// between the loggers so that any file can import one logger
// and have the stats tracked correctly
export let fshOnlineLogger = sushiUtils.logger;
export function setCurrentLogger(loggerName) {
export function setCurrentLogger(loggerName, loggerLevel) {
if (loggerName === 'sushi') {
fshOnlineLogger = sushiUtils.logger;
} else if (loggerName === 'gofsh') {
fshOnlineLogger = gofshUtils.logger;
}
fshOnlineLogger.level = loggerLevel;
}
167 changes: 155 additions & 12 deletions tests/components/FSHControls.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,14 @@ it('calls GoFSH function and returns FSH', async () => {

await waitFor(() => {
expect(resetLogMessages).toHaveBeenCalledTimes(1);
expect(runGoFSHSpy).toHaveBeenCalledWith([JSON.stringify(examplePatient, null, 2)], {
dependencies: [],
indent: false
}); // No IG resource added because canonical and version set to defaults
expect(runGoFSHSpy).toHaveBeenCalledWith(
[JSON.stringify(examplePatient, null, 2)],
{
dependencies: [],
indent: false
},
'info'
); // No IG resource added because canonical and version set to defaults
expect(onGoFSHClick).toHaveBeenCalledTimes(2);
expect(onGoFSHClick).toHaveBeenCalledWith('', true); // Loading
expect(onGoFSHClick).toHaveBeenCalledWith(simpleFsh, false);
Expand Down Expand Up @@ -191,7 +195,8 @@ it('calls GoFSH with user provided canonical and version in mini ImplementationG
expect(resetLogMessages).toHaveBeenCalledTimes(1);
expect(runGoFSHSpy).toHaveBeenCalledWith(
[JSON.stringify(examplePatient, null, 2), JSON.stringify(expectedIgResource, null, 2)], // Adds IG resource with canonical and version
{ dependencies: [], indent: false }
{ dependencies: [], indent: false },
'info'
);
expect(onGoFSHClick).toHaveBeenCalledTimes(2);
expect(onGoFSHClick).toHaveBeenCalledWith('', true); // Loading
Expand Down Expand Up @@ -231,16 +236,154 @@ it('calls GoFSH with the indent option if the configuration checkbox is checked'

await waitFor(() => {
expect(resetLogMessages).toHaveBeenCalledTimes(1);
expect(runGoFSHSpy).toHaveBeenCalledWith([JSON.stringify(examplePatient, null, 2)], {
dependencies: [],
indent: true
}); // No IG resource added because canonical and version set to defaults
expect(runGoFSHSpy).toHaveBeenCalledWith(
[JSON.stringify(examplePatient, null, 2)],
{
dependencies: [],
indent: true
},
'info'
); // No IG resource added because canonical and version set to defaults
expect(onGoFSHClick).toHaveBeenCalledTimes(2);
expect(onGoFSHClick).toHaveBeenCalledWith('', true); // Loading
expect(onGoFSHClick).toHaveBeenCalledWith(simpleFsh, false);
});
});

it('calls GoFSH with the logger level debug if the configuration checkbox is checked', async () => {
const examplePatient = {
resourceType: 'Patient',
id: 'MyPatient',
gender: 'female'
};
const simpleFsh = ['Instance: MyPatient', 'InstanceOf: Patient', 'Usage: #example', '* gender = #female'].join('\n');
const onGoFSHClick = vi.fn();
const resetLogMessages = vi.fn();
let debugLevel = false;
const setIsDebugConsoleChecked = vi.fn(() => {
debugLevel = !debugLevel;
});

const runGoFSHSpy = vi.spyOn(fshHelpers, 'runGoFSH').mockReset().mockResolvedValue({ fsh: simpleFsh, config: {} });
const { getByRole, getByLabelText, rerender } = render(
<FSHControls
onGoFSHClick={onGoFSHClick}
gofshText={[{ def: JSON.stringify(examplePatient, null, 2) }]}
resetLogMessages={resetLogMessages}
exampleConfig={[]}
setIsDebugConsoleChecked={setIsDebugConsoleChecked}
isDebugConsoleChecked={debugLevel}
/>,
container
);

const configButton = getByRole('button', { name: /Configuration/i });
fireEvent.click(configButton);
const debugLevelCheckbox = getByLabelText('Debug level console messages');
expect(debugLevelCheckbox).not.toBeChecked();
fireEvent.click(debugLevelCheckbox);

const button = document.querySelector('[testid=GoFSH-button]');
act(() => {
button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
});
expect(runGoFSHSpy).toHaveBeenCalledWith(
[JSON.stringify(examplePatient, null, 2)],
{
dependencies: [],
indent: false
},
'info'
);

rerender(
<FSHControls
onGoFSHClick={onGoFSHClick}
gofshText={[{ def: JSON.stringify(examplePatient, null, 2) }]}
resetLogMessages={resetLogMessages}
exampleConfig={[]}
setIsDebugConsoleChecked={setIsDebugConsoleChecked}
isDebugConsoleChecked={debugLevel}
/>,
container
);
act(() => {
button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
});

await waitFor(() => {
expect(debugLevelCheckbox).toBeChecked();
expect(resetLogMessages).toHaveBeenCalledTimes(2);
expect(runGoFSHSpy).toHaveBeenCalledWith(
[JSON.stringify(examplePatient, null, 2)],
{
dependencies: [],
indent: false
},
'debug'
); // No IG resource added because canonical and version set to defaults
});
});

it('calls runSUSHI with the logger level debug if the configuration checkbox is checked', async () => {
const onClick = vi.fn();
const resetLogMessages = vi.fn();
let debugLevel = false;
const setIsDebugConsoleChecked = vi.fn(() => {
debugLevel = !debugLevel;
});

const runSUSHISpy = vi.spyOn(fshHelpers, 'runSUSHI').mockReset().mockResolvedValue(goodSUSHIPackage);
const { getByRole, getByLabelText, rerender } = render(
<FSHControls
onSUSHIClick={onClick}
resetLogMessages={resetLogMessages}
exampleConfig={[]}
setIsDebugConsoleChecked={setIsDebugConsoleChecked}
isDebugConsoleChecked={debugLevel}
/>,
container
);

const configButton = getByRole('button', { name: /Configuration/i });
fireEvent.click(configButton);
const debugLevelCheckbox = getByLabelText('Debug level console messages');
expect(debugLevelCheckbox).not.toBeChecked();
fireEvent.click(debugLevelCheckbox);

const button = document.querySelector('[testid=Button]');
act(() => {
button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
});
const expectedConfig = {
canonical: 'http://example.org',
version: '1.0.0',
FSHOnly: true,
fhirVersion: ['4.0.1']
};
expect(runSUSHISpy).toHaveBeenCalledWith(undefined, expectedConfig, [], 'info');

rerender(
<FSHControls
onSUSHIClick={onClick}
resetLogMessages={resetLogMessages}
exampleConfig={[]}
setIsDebugConsoleChecked={setIsDebugConsoleChecked}
isDebugConsoleChecked={debugLevel}
/>,
container
);
act(() => {
button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
});

await waitFor(() => {
expect(debugLevelCheckbox).toBeChecked();
expect(resetLogMessages).toHaveBeenCalledTimes(2);
expect(runSUSHISpy).toHaveBeenCalledWith(undefined, expectedConfig, [], 'debug');
});
});

it('displays code with line wrapping in the code editors if the configuration checkbox is checked', async () => {
const examplePatient = {
resourceType: 'Patient',
Expand Down Expand Up @@ -313,7 +456,7 @@ it('uses user provided canonical when calling runSUSHI', async () => {
fhirVersion: ['4.0.1']
};
await waitFor(() => {
expect(runSUSHISpy).toHaveBeenCalledWith(undefined, expectedConfig, []); // Includes new config
expect(runSUSHISpy).toHaveBeenCalledWith(undefined, expectedConfig, [], 'info'); // Includes new config
});
});

Expand Down Expand Up @@ -347,7 +490,7 @@ it('uses user provided version when calling runSUSHI', async () => {
};

await waitFor(() => {
expect(runSUSHISpy).toHaveBeenCalledWith(undefined, expectedConfig, []); // Includes new version
expect(runSUSHISpy).toHaveBeenCalledWith(undefined, expectedConfig, [], 'info'); // Includes new version
});
});

Expand Down Expand Up @@ -381,7 +524,7 @@ it('uses user provided dependencies when calling runSUSHI', async () => {
];

await waitFor(() => {
expect(runSUSHISpy).toHaveBeenCalledWith(undefined, defaultConfig, expectedDependencies); // Called with new dependencies
expect(runSUSHISpy).toHaveBeenCalledWith(undefined, defaultConfig, expectedDependencies, 'info'); // Called with new dependencies
});
});

Expand Down

0 comments on commit b9a4685

Please sign in to comment.