diff --git a/Testfunctions - Copy/loader.test.js b/Testfunctions - Copy/loader.test.js new file mode 100644 index 000000000..5a9ca61d1 --- /dev/null +++ b/Testfunctions - Copy/loader.test.js @@ -0,0 +1,19 @@ + +const {JSDOM} = require('jsdom') + +//test for successful upload +test("Successful upload", () => { + const handleUpload = jest.fn() + const mockFile = new File([], "dummyFile"); + const mockFilename = "dummyFilename"; + + global.changeStatus = jest.fn(); + + return handleUpload(mockFile, mockFilename) + + expect(global.changeStatus).toHaveBeenCalledWith("UPLOAD", "dummyFile uploaded successfully"); + +}); + +//test for the upload function + diff --git a/Testfunctions - Copy/toolbar.test.js b/Testfunctions - Copy/toolbar.test.js new file mode 100644 index 000000000..3bce33b5b --- /dev/null +++ b/Testfunctions - Copy/toolbar.test.js @@ -0,0 +1,41 @@ + +const {JSDOM} = require('jsdom') + +//test for the selected function +describe ('selected function', ()=>{ + test('should add checked class to all elements until reaching an element with class "multidown"',()=>{ + const selected = jest.fn() + + const dom = new JSDOM(''); + const element = dom.window.document.querySelector('li') + selected(element) + + + expect(element.classList.contains('checked')).toBe(false) + }) + + +}) + + + + + + // test default values +test('gets default status of form elements', () => { + const getStatus = jest.fn().mockReturnValue({ + select: 'option1', + checkbox: false, + radio: 'radio1' + }); + + expect(getStatus({})).toEqual({ + select: 'option1', + checkbox: false, + radio: 'radio1' + }); + }); + + + + \ No newline at end of file diff --git a/Testfunctions - Copy/uicallback.test.js b/Testfunctions - Copy/uicallback.test.js new file mode 100644 index 000000000..9a93d54f7 --- /dev/null +++ b/Testfunctions - Copy/uicallback.test.js @@ -0,0 +1,184 @@ + + +// test for toggle viewer mode: + +const { JSDOM } = require('jsdom'); +const { toggleSideMenu } = require('../apps/heatmap/uicallbacks') + +test('calls openSecondaryViewer when checked is true', () => { + const openSecondaryViewer = jest.fn(); + const toggleViewerMode = ({ checked }) => { + if (checked) { + openSecondaryViewer(); + } + }; + toggleViewerMode({ checked: true }); + expect(openSecondaryViewer).toHaveBeenCalled(); +}); + + + + +// test for closeSecondary viewer + + + + + + + + +describe('closed viewer function', () => { + + //settting up a basic dom structure using JSDOM + + const dom = new JSDOM(` + + +
+
+ + + + `) + + //global objects for window and document + + global.window = dom.window; + global.document = dom.window.document +}) +test('closeSecondaryViewer function should update classes and elements correctly', () => { + const closeSecondaryViewer = jest.fn() + + const $CAMIC = { + viewer: { + controls: { + bottomright: { style: { display: '' } } + }, + removeHandler: jest.fn() + } + }; + + const $UI = { + lockerPanel: { style: { display: 'block' } }, + toolbar: { + getSubTool: jest.fn(() => ({ + querySelector: jest.fn(() => ({ checked: true })) + })) + }, + layersViewerMinor: { + toggleAllItems: jest.fn(), + setting: { data: [{ layer: 'example' }] } + } + }; + + const Loading = { close: jest.fn() }; + + // Call the function + closeSecondaryViewer(); + + // Assertions + expect(document.getElementById('main_viewer').classList.contains('main')).toBe(true); + expect(document.getElementById('main_viewer').classList.contains('left')).toBe(false); + expect(document.getElementById('minor_viewer').classList.contains('none')).toBe(true); + expect(document.getElementById('minor_viewer').classList.contains('right')).toBe(false); + expect($CAMIC.viewer.controls.bottomright.style.display).toBe(''); + + + + + + + + + +}); + + +const $UI = { + toolbar: { + changeMainToolStatus: jest.fn(), + }, +}; +// testing the toggle side menu function +describe('toggleSlideMenu', () => { + it('should changeMainToolStatus when isOpen is false', () => { + const opt = { + isOpen: false, + target: { id: 'sidebar_menu_1' }, + }; + + const changeMainToolStatusMock = jest.fn(); + $UI.toolbar.changeMainToolStatus = changeMainToolStatusMock; + + function toggleSideMenu(options) { + if (!options.isOpen) { + $UI.toolbar.changeMainToolStatus('menu_1', false); + } + } + + toggleSideMenu(opt); + + expect(changeMainToolStatusMock).toHaveBeenCalledWith('menu_1', false); + }); +}); + + +// testing for the open secondary viewer +describe('openSecondaryViewer function', () => { + beforeEach(() => { + //settting up a basic dom structure using JSDOM + + const dom = new JSDOM(` + + +
+
+ + + +`) + + //global objects for window and document + + global.window = dom.window; + global.document = dom.window.document + + + + }) + + afterEach(() => { + delete global.window; + delete global.document; + + }) + test('should update classes and call multSelectorAction after timeout', () => { + const openSecondaryViewer = jest.fn(); + const multSelectorAction = jest.fn() + // Mock necessary DOM elements + + + // Call the function + openSecondaryViewer(); + + + + // Assertions + const main = document.getElementById('main_viewer'); + const minor = document.getElementById('minor_viewer'); + expect(minor.classList.contains('none')).toBe(true); + expect(minor.classList.contains('right')).toBe(false); + // Simulate setTimeout + jest.runAllTimers(); + + + }); +}); + + + + + + + diff --git a/Testfunctions/loader.test.js b/Testfunctions/loader.test.js new file mode 100644 index 000000000..5a9ca61d1 --- /dev/null +++ b/Testfunctions/loader.test.js @@ -0,0 +1,19 @@ + +const {JSDOM} = require('jsdom') + +//test for successful upload +test("Successful upload", () => { + const handleUpload = jest.fn() + const mockFile = new File([], "dummyFile"); + const mockFilename = "dummyFilename"; + + global.changeStatus = jest.fn(); + + return handleUpload(mockFile, mockFilename) + + expect(global.changeStatus).toHaveBeenCalledWith("UPLOAD", "dummyFile uploaded successfully"); + +}); + +//test for the upload function + diff --git a/Testfunctions/toolbar.test.js b/Testfunctions/toolbar.test.js new file mode 100644 index 000000000..3bce33b5b --- /dev/null +++ b/Testfunctions/toolbar.test.js @@ -0,0 +1,41 @@ + +const {JSDOM} = require('jsdom') + +//test for the selected function +describe ('selected function', ()=>{ + test('should add checked class to all elements until reaching an element with class "multidown"',()=>{ + const selected = jest.fn() + + const dom = new JSDOM(''); + const element = dom.window.document.querySelector('li') + selected(element) + + + expect(element.classList.contains('checked')).toBe(false) + }) + + +}) + + + + + + // test default values +test('gets default status of form elements', () => { + const getStatus = jest.fn().mockReturnValue({ + select: 'option1', + checkbox: false, + radio: 'radio1' + }); + + expect(getStatus({})).toEqual({ + select: 'option1', + checkbox: false, + radio: 'radio1' + }); + }); + + + + \ No newline at end of file diff --git a/Testfunctions/uicallback.test.js b/Testfunctions/uicallback.test.js new file mode 100644 index 000000000..9a93d54f7 --- /dev/null +++ b/Testfunctions/uicallback.test.js @@ -0,0 +1,184 @@ + + +// test for toggle viewer mode: + +const { JSDOM } = require('jsdom'); +const { toggleSideMenu } = require('../apps/heatmap/uicallbacks') + +test('calls openSecondaryViewer when checked is true', () => { + const openSecondaryViewer = jest.fn(); + const toggleViewerMode = ({ checked }) => { + if (checked) { + openSecondaryViewer(); + } + }; + toggleViewerMode({ checked: true }); + expect(openSecondaryViewer).toHaveBeenCalled(); +}); + + + + +// test for closeSecondary viewer + + + + + + + + +describe('closed viewer function', () => { + + //settting up a basic dom structure using JSDOM + + const dom = new JSDOM(` + + +
+
+ + + + `) + + //global objects for window and document + + global.window = dom.window; + global.document = dom.window.document +}) +test('closeSecondaryViewer function should update classes and elements correctly', () => { + const closeSecondaryViewer = jest.fn() + + const $CAMIC = { + viewer: { + controls: { + bottomright: { style: { display: '' } } + }, + removeHandler: jest.fn() + } + }; + + const $UI = { + lockerPanel: { style: { display: 'block' } }, + toolbar: { + getSubTool: jest.fn(() => ({ + querySelector: jest.fn(() => ({ checked: true })) + })) + }, + layersViewerMinor: { + toggleAllItems: jest.fn(), + setting: { data: [{ layer: 'example' }] } + } + }; + + const Loading = { close: jest.fn() }; + + // Call the function + closeSecondaryViewer(); + + // Assertions + expect(document.getElementById('main_viewer').classList.contains('main')).toBe(true); + expect(document.getElementById('main_viewer').classList.contains('left')).toBe(false); + expect(document.getElementById('minor_viewer').classList.contains('none')).toBe(true); + expect(document.getElementById('minor_viewer').classList.contains('right')).toBe(false); + expect($CAMIC.viewer.controls.bottomright.style.display).toBe(''); + + + + + + + + + +}); + + +const $UI = { + toolbar: { + changeMainToolStatus: jest.fn(), + }, +}; +// testing the toggle side menu function +describe('toggleSlideMenu', () => { + it('should changeMainToolStatus when isOpen is false', () => { + const opt = { + isOpen: false, + target: { id: 'sidebar_menu_1' }, + }; + + const changeMainToolStatusMock = jest.fn(); + $UI.toolbar.changeMainToolStatus = changeMainToolStatusMock; + + function toggleSideMenu(options) { + if (!options.isOpen) { + $UI.toolbar.changeMainToolStatus('menu_1', false); + } + } + + toggleSideMenu(opt); + + expect(changeMainToolStatusMock).toHaveBeenCalledWith('menu_1', false); + }); +}); + + +// testing for the open secondary viewer +describe('openSecondaryViewer function', () => { + beforeEach(() => { + //settting up a basic dom structure using JSDOM + + const dom = new JSDOM(` + + +
+
+ + + +`) + + //global objects for window and document + + global.window = dom.window; + global.document = dom.window.document + + + + }) + + afterEach(() => { + delete global.window; + delete global.document; + + }) + test('should update classes and call multSelectorAction after timeout', () => { + const openSecondaryViewer = jest.fn(); + const multSelectorAction = jest.fn() + // Mock necessary DOM elements + + + // Call the function + openSecondaryViewer(); + + + + // Assertions + const main = document.getElementById('main_viewer'); + const minor = document.getElementById('minor_viewer'); + expect(minor.classList.contains('none')).toBe(true); + expect(minor.classList.contains('right')).toBe(false); + // Simulate setTimeout + jest.runAllTimers(); + + + }); +}); + + + + + + + diff --git a/apps/admin/admin.html b/apps/admin/admin.html index cd93f55c8..8ccf16402 100644 --- a/apps/admin/admin.html +++ b/apps/admin/admin.html @@ -33,6 +33,11 @@ + + + + + diff --git a/apps/admin/admin.js b/apps/admin/admin.js index cbd1c95e1..980117924 100644 --- a/apps/admin/admin.js +++ b/apps/admin/admin.js @@ -1,3 +1,34 @@ + + +const { JSDOM } = require('jsdom'); +const jquery = require('jquery'); +const $ = require('jquery') + +const { window } = new JSDOM(''); + +global.window = window; +global.document = window.document; + + +console.log(typeof $) + + + +console.log(typeof window) +// Create a new JSDOM instance + + +// Assign the window and document to global variables + +// Now you can use jQuery in your tests + + + + + + + + const pathConfig = { 'collection': '../collection/collection.html', 'user': '../user/user.html', @@ -5,6 +36,7 @@ const pathConfig = { }; function calculateMainHeight() { + const height = $(window).height() - $('#nav-bar').height(); $('#main').height(height); } @@ -20,3 +52,5 @@ function redirectPath(link, url) { $(link).addClass('active'); $('#main iframe').attr('src', url); } + +module.exports = admin diff --git a/apps/admin/jsConfig.js b/apps/admin/jsConfig.js new file mode 100644 index 000000000..c3f798787 --- /dev/null +++ b/apps/admin/jsConfig.js @@ -0,0 +1,3 @@ +const jQuery = require('jquery'); +global.$ = jQuery; +global.jQuery = jQuery; \ No newline at end of file diff --git a/apps/landing/landing.html b/apps/landing/landing.html index e442429ca..1409c7cfc 100644 --- a/apps/landing/landing.html +++ b/apps/landing/landing.html @@ -4,20 +4,23 @@ - + + - + + - + - - + + - + -
+
-
+
-
+
-

caMicroscope

+

caMicroscope

-
+
- + -
-

caMicroscope is a tool to view, annotate, and analyze biomedical images.

- +
+

caMicroscope is a tool to view, annotate, and analyze biomedical images.

+ -
+
-
-
- -
-

caMicroscope

-

Use camicroscope to explore and mark slides uploaded. If this is a restricted access deployment, you will be prompted to log in here.

- More -
-
-
- -
-

Documentation

-

Read documentation for using and developing caMicroscope.

- More -
-
-
- -
+
+
+ +
+

caMicroscope

+

Use camicroscope to explore and mark slides uploaded. If this is a restricted + access deployment, you will be prompted to log in here.

+ More +
+
+
+ +
+

Documentation

+

Read documentation for using and developing caMicroscope.

+ More +
+
+
+ +
- + - - - - + + + - + - + - + - + + - + \ No newline at end of file diff --git a/apps/loader/loader.js b/apps/loader/loader.js index f41fb9bc0..1861012bf 100644 --- a/apps/loader/loader.js +++ b/apps/loader/loader.js @@ -99,6 +99,7 @@ function changeStatus(step, text, reset=true) { } } +//refactored the handleupload function function handleUpload(file, filename) { var data = new FormData(); data.append('file', file); @@ -111,9 +112,16 @@ function handleUpload(file, filename) { }).then( (response) => response.json(), // if the response is a JSON object ).then( - (success) => changeStatus('UPLOAD', success), // Handle the success response object + (success) =>{ changeStatus('UPLOAD', success) + return success + //return success data for chaining + // Handle the success response object + } ).catch( - (error) => changeStatus('UPLOAD', error), // Handle the error response object + (error) => {changeStatus('UPLOAD', error); + throw error; + } + // Handle the error response object ); } diff --git a/apps/signup/Signup.test.js b/apps/signup/Signup.test.js new file mode 100644 index 000000000..92f61942f --- /dev/null +++ b/apps/signup/Signup.test.js @@ -0,0 +1,94 @@ +// Importing the addUser function +const addUser = require('./signup') +const Store = require('../../core/Store') + + + +const storeMock = { + getUserPermissions: jest.fn().mockResolvedValue({}), // Mock any methods you use from the Store class + requestToCreateUser: jest.fn().mockResolvedValue({}) + // Add more mock methods as needed +}; + +jest.mock('../../data/Store', () => { + return jest.fn(() => storeMock); +}); + +// Simulating functions and objects +document.getElementById = jest.fn(); +window.alert = jest.fn(); +fetch = jest.fn(() => Promise.resolve({ status: 200, json: () => Promise.resolve({}) })); + +describe('addUser', () => { + beforeEach(() => { + // Resetting mocks before each test + jest.clearAllMocks(); + }); + + test('should display an alert message for invalid email', () => { + document.getElementById.mockReturnValueOnce({ value: 'invalidemail' }); + + addUser(); + + // Asserting + expect(window.alert).toHaveBeenCalledWith('Please enter a valid email'); + expect(fetch).not.toHaveBeenCalled(); // No HTTP request should be initiated + }); + + test('should register user with admin type when attribute is "3"', async () => { + document.getElementById.mockReturnValueOnce({ value: 'validemail@example.com' }); + document.getElementById.mockReturnValueOnce({ value: 'filtersValue' }); + document.getElementById.mockReturnValueOnce({ selectedIndex: 0, options: [{ value: '3' }] }); + fetch.mockReturnValueOnce(Promise.resolve({ exists: true })); + + await addUser(); + + expect(fetch).toHaveBeenCalledWith(expect.any(String), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ email: 'validemail@example.com', userType: 'Admin', userFilter: 'filtersValue' }), + }); + expect(window.alert).toHaveBeenCalledWith('User registered successfully'); + }); + + // Test for creating a user + test('should request to create a user if token does not exist and user has permission', async () => { + // Arranging + document.getElementById.mockReturnValueOnce({ value: 'validemmail@example.com' }); + document.getElementById.mockReturnValueOnce({ value: 'filtersValue' }); + document.getElementById.mockReturnValueOnce({ selectedIndex: 0, options: [{ value: '1' }] }); + fetch.mockReturnValueOnce(Promise.resolve({ exists: false })); + const requestToCreateUserMock = jest.spyOn(store, 'requestToCreateUser').mockImplementation(() => {}); + + // Acting + await addUser(); + + // Asserting + expect(requestToCreateUserMock).toHaveBeenCalledWith('validemail@example.com', 'filtersValue', 'Null'); + expect(fetch).not.toHaveBeenCalled(); + expect(window.alert).not.toHaveBeenCalled(); + }); + + test('should handle error when user registration fails', async () => { + // Arranging + document.getElementById.mockReturnValueOnce({ value: 'validemail@example.com' }); + document.getElementById.mockReturnValueOnce({ value: 'filtersValue' }); + document.getElementById.mockReturnValueOnce({ selectedIndex: 0, options: [{ value: '3' }] }); + fetch.mockReturnValueOnce(Promise.resolve({ status: 400 })); + + // Acting + await addUser(); + + // Asserting + expect(fetch).toHaveBeenCalledWith(expect.any(String), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ email: 'validemail@example.com', userType: 'Admin', userFilter: 'filtersValue' }), + }); + expect(window.alert).toHaveBeenCalledWith('failed to sign up user'); + }); +}); diff --git a/apps/signup/signup.html b/apps/signup/signup.html index 10243698a..7e5b8ef55 100644 --- a/apps/signup/signup.html +++ b/apps/signup/signup.html @@ -51,8 +51,11 @@ + + + + + + + + + +
+
+
+
+
+
+ +
+ +
+
+
+
+ + +
+
+ + +
+    +
+ +
+ +    +
+
+ + + +
+
+
- -