diff --git a/kibana-reports/package.json b/kibana-reports/package.json index 547bde3d..7652f19a 100644 --- a/kibana-reports/package.json +++ b/kibana-reports/package.json @@ -33,6 +33,7 @@ "cron-validator": "^1.1.1", "dompurify": "^2.1.1", "elastic-builder": "^2.7.1", + "jest-fetch-mock": "^3.0.3", "jquery": "^3.5.0", "jsdom": "^16.4.0", "json-2-csv": "^3.7.6", @@ -49,6 +50,7 @@ "regenerator-runtime": "^0.13.7", "set-interval-async": "1.0.33", "showdown": "^1.9.1", + "sinon": "^9.2.0", "uuid": "^8.1.0", "ws": "^7.2.3" }, diff --git a/kibana-reports/public/components/main/__tests__/__utils__/main_utils_test_utils.tsx b/kibana-reports/public/components/main/__tests__/__utils__/main_utils_test_utils.tsx new file mode 100644 index 00000000..5dabb44b --- /dev/null +++ b/kibana-reports/public/components/main/__tests__/__utils__/main_utils_test_utils.tsx @@ -0,0 +1,121 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + + export const reportTableMockResponse = [ + { + _id: "123456", + _index: "test", + _score: 1, + _source: { + last_updated: 123456789, + query_url: "test_query_url_value.com", + report_definition: { + delivery: { + delivery_type: "Kibana user", + delivery_params: { + kibana_recipients: [] + } + }, + report_params: { + report_name: "Test report table response", + description: "description", + report_source: "Dashboard", + core_params: { + base_url: "test_base_url.com", + header: "", + footer: "", + report_format: "pdf", + time_duration: "PT30M", + window_height: 800, + window_width: 1200 + } + }, + trigger: { + trigger_type: "On demand" + }, + state: "Created", + time_created: 123456780, + time_from: 123456780, + time_to: 123456799, + } + }, + _type: "doc" + } +]; + +export const mockReportsTableItems = [ + { + id: '123456', + reportName: 'Test report table response', + type: 'On demand', + sender: '—', + kibanaRecipients: '—', + emailRecipients: '—', + reportSource: 'Dashboard', + timeCreated: undefined, + state: undefined, + url: 'test_query_url_value.com', + format: 'pdf' + } +]; + +export const reportDefinitionsTableMockResponse = [ + { + _index: 'report_definition', + _type: '_doc', + _id: '42MmKXUBDW-VXnk7pa6d', + _score: 1, + _source: { + report_definition: { report_params: + { report_name: 'schedule definition', + report_source: 'Dashboard', + description: 'description', + core_params: + { base_url: 'test_base_url.com', + report_format: 'pdf', + header: '', + footer: '', + time_duration: 'PT30M', + window_width: 1200, + window_height: 800 } }, + delivery: + { delivery_type: 'Kibana user', + delivery_params: { kibana_recipients: [] } }, + trigger: + { trigger_type: 'Schedule', + trigger_params: + { enabled_time: 1602713178321, + schedule: { + period: 1, + interval: 'DAYS' + }, + schedule_type: 'Recurring', + enabled: false } }, + time_created: 1602713199604, + last_updated: 1602713211007, + status: 'Disabled' } + } + } +]; + +export const reportDefinitionsTableMockContent = [ { id: '42MmKXUBDW-VXnk7pa6d', +reportName: 'schedule definition', +type: 'Schedule', +owner: '—', +source: 'Dashboard', +baseUrl: 'test_base_url.com', +lastUpdated: 1602713211007, +details: 'Recurring', +status: 'Disabled' } ] \ No newline at end of file diff --git a/kibana-reports/public/components/main/__tests__/main_utils.test.tsx b/kibana-reports/public/components/main/__tests__/main_utils.test.tsx new file mode 100644 index 00000000..3d1746e1 --- /dev/null +++ b/kibana-reports/public/components/main/__tests__/main_utils.test.tsx @@ -0,0 +1,132 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import { + humanReadableDate, + extractFilename, + extractFileFormat, + getFileFormatPrefix, + addReportsTableContent, + addReportDefinitionsTableContent, + removeDuplicatePdfFileFormat, + readStreamToFile, + generateReport, + generateReportById, +} from '../main_utils'; +import { + reportDefinitionsTableMockResponse, + mockReportsTableItems, + reportTableMockResponse, + reportDefinitionsTableMockContent, +} from './__utils__/main_utils_test_utils'; +import sinon from 'sinon'; +import httpClientMock from '../../../../test/httpMockClient'; + +describe('main_utils tests', () => { + global.URL.createObjectURL = jest.fn(); + let mockElement = document.createElement('a'); + mockElement.download = 'string'; + mockElement.click = function name() {}; + sinon.stub(document, 'createElement').returns(mockElement); + + test('test humanReadableDate', () => { + const readableDate = new Date(2018, 11, 24, 10, 33, 30); + const humanReadable = humanReadableDate(readableDate); + + expect(humanReadable).toBe('Mon Dec 24 2018 @ 10:33:30 AM'); + }); + + test('test extractFileName', () => { + const fullFile = 'test_file_name_extracted_correctly.pdf'; + const fileName = extractFilename(fullFile); + + expect(fileName).toBe('test_file_name_extracted_correctly'); + }); + + test('test extractFileFormat', () => { + const fullFile = 'test_file_format_extracted_correctly.png'; + const fileFormat = extractFileFormat(fullFile); + + expect(fileFormat).toBe('png'); + }); + + test('test getFileFormatPrefix', () => { + const fileFormat = 'pdf'; + const fileFormatPrefix = getFileFormatPrefix(fileFormat); + + expect(fileFormatPrefix).toBe('data:pdf;base64,'); + }); + + test('test addReportsTableContent', () => { + const reportsTableItems = addReportsTableContent(reportTableMockResponse); + + expect(reportsTableItems).toStrictEqual(mockReportsTableItems); + }); + + test('test addReportDefinitionsTableContent', () => { + const reportDefinitionsTableItems = addReportDefinitionsTableContent( + reportDefinitionsTableMockResponse + ); + + expect(reportDefinitionsTableItems).toStrictEqual( + reportDefinitionsTableMockContent + ); + }); + + test('test removeDuplicatePdfFileFormat', () => { + const duplicateFormat = 'test_duplicate_remove.pdf.pdf'; + const duplicateRemoved = removeDuplicatePdfFileFormat(duplicateFormat); + + expect(duplicateRemoved).toBe('test_duplicate_remove.pdf'); + }); + + test('test readStreamToFile csv compile', () => { + const stream = + 'category,customer_gender\n' + + 'c1,Male\n' + + 'c2,Male\n' + + 'c3,Male\n' + + 'c4,Male\n' + + 'c5,Male'; + + const fileFormat = 'csv'; + const fileName = 'test_data_report.csv'; + readStreamToFile(stream, fileFormat, fileName); + }); + + test('test readStreamToFile pdf compile', () => { + const stream = 'data:pdf;base64,zxvniaorbguw40absdoanlsdf'; + const fileFormat = 'pdf'; + const fileName = 'test_pdf_report.pdf'; + readStreamToFile(stream, fileFormat, fileName); + }); + + test('test generateReport compile', () => { + const metadata = {}; + generateReport(metadata, httpClientMock); + }); + + test('test generateReportById compile', () => { + const reportId = '1'; + const handleSuccessToast = jest.fn(); + const handleErrorToast = jest.fn(); + generateReportById( + reportId, + httpClientMock, + handleSuccessToast, + handleErrorToast + ); + }); +}); diff --git a/kibana-reports/public/components/main/main_utils.tsx b/kibana-reports/public/components/main/main_utils.tsx index ed7854be..55b90e87 100644 --- a/kibana-reports/public/components/main/main_utils.tsx +++ b/kibana-reports/public/components/main/main_utils.tsx @@ -13,7 +13,6 @@ * permissions and limitations under the License. */ -import { get } from 'lodash'; import 'babel-polyfill'; export const fileFormatsUpper = { @@ -98,24 +97,11 @@ export const addReportDefinitionsTableContent = (data: any) => { return reportDefinitionsTableItems; }; -export const getReportSettingDashboardOptions = (data) => { - let index; - let dashboardOptions = []; - for (index = 0; index < data.length; ++index) { - let entry = { - value: get(data, [index, '_id']).substring(10), - text: get(data, [index, '_source', 'dashboard', 'title']), - }; - dashboardOptions.push(entry); - } - return dashboardOptions; -}; - export const removeDuplicatePdfFileFormat = (filename) => { return filename.substring(0, filename.length - 4); }; -const readDataReportToFile = async ( +export const readDataReportToFile = async ( stream: string, fileFormat: string, fileName: string diff --git a/kibana-reports/test/httpMockClient.js b/kibana-reports/test/httpMockClient.js index 27b980ce..e3a66e19 100644 --- a/kibana-reports/test/httpMockClient.js +++ b/kibana-reports/test/httpMockClient.js @@ -17,10 +17,17 @@ const httpClientMock = jest.fn(); httpClientMock.delete = jest.fn(); httpClientMock.get = jest.fn(() => ({ - then: jest.fn(() => ({ catch: jest.fn() })), + + then: jest.fn(() => ({ + catch: jest.fn() + })), })); httpClientMock.head = jest.fn(); -httpClientMock.post = jest.fn(); +httpClientMock.post = jest.fn(() => ({ + then: jest.fn(() => ({ + catch: jest.fn() + })), +})); httpClientMock.put = jest.fn(); export default httpClientMock; diff --git a/kibana-reports/yarn.lock b/kibana-reports/yarn.lock index a626924f..0568186a 100644 --- a/kibana-reports/yarn.lock +++ b/kibana-reports/yarn.lock @@ -1455,20 +1455,42 @@ hoist-non-react-statics "^3.3.2" react-native-safe-area-view "^0.14.9" -"@sinonjs/commons@^1.7.0": +"@sinonjs/commons@^1", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.1": version "1.8.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw== dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^6.0.1": +"@sinonjs/fake-timers@^6.0.0", "@sinonjs/fake-timers@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== dependencies: "@sinonjs/commons" "^1.7.0" +"@sinonjs/formatio@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-5.0.1.tgz#f13e713cb3313b1ab965901b01b0828ea6b77089" + integrity sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ== + dependencies: + "@sinonjs/commons" "^1" + "@sinonjs/samsam" "^5.0.2" + +"@sinonjs/samsam@^5.0.2", "@sinonjs/samsam@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.2.0.tgz#fcff83ab86f83b5498f4a967869c079408d9b5eb" + integrity sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw== + dependencies: + "@sinonjs/commons" "^1.6.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" + +"@sinonjs/text-encoding@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" + integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== + "@testing-library/dom@^7.22.3": version "7.24.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.24.0.tgz#b50066100947e4d1bd0f2f6855c7ff3f2a8770e2" @@ -3262,6 +3284,13 @@ cross-env@^6.0.3: dependencies: cross-spawn "^7.0.0" +cross-fetch@^3.0.4: + version "3.0.6" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c" + integrity sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ== + dependencies: + node-fetch "2.6.1" + cross-spawn@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" @@ -3542,6 +3571,11 @@ diff-sequences@^26.3.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.3.0.tgz#62a59b1b29ab7fd27cef2a33ae52abe73042d0a2" integrity sha512-5j5vdRcw3CNctePNYN0Wy2e/JbWT6cAYnXv5OuqPhDpyCGc0uLu2TK0zOCJWNB9kOIfYMSpIulRaDgIi4HJ6Ig== +diff@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -5665,6 +5699,14 @@ jest-environment-node@^26.3.0: jest-mock "^26.3.0" jest-util "^26.3.0" +jest-fetch-mock@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz#31749c456ae27b8919d69824f1c2bd85fe0a1f3b" + integrity sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw== + dependencies: + cross-fetch "^3.0.4" + promise-polyfill "^8.1.3" + jest-get-type@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" @@ -6075,6 +6117,11 @@ jsx-ast-utils@^2.4.1: array-includes "^3.1.1" object.assign "^4.1.0" +just-extend@^4.0.2: + version "4.1.1" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.1.1.tgz#158f1fdb01f128c411dc8b286a7b4837b3545282" + integrity sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA== + keymirror@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/keymirror/-/keymirror-0.1.1.tgz#918889ea13f8d0a42e7c557250eee713adc95c35" @@ -6664,6 +6711,22 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +nise@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/nise/-/nise-4.0.4.tgz#d73dea3e5731e6561992b8f570be9e363c4512dd" + integrity sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A== + dependencies: + "@sinonjs/commons" "^1.7.0" + "@sinonjs/fake-timers" "^6.0.0" + "@sinonjs/text-encoding" "^0.7.1" + just-extend "^4.0.2" + path-to-regexp "^1.7.0" + +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-gyp@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" @@ -7389,6 +7452,11 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= +promise-polyfill@^8.1.3: + version "8.1.3" + resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.1.3.tgz#8c99b3cf53f3a91c68226ffde7bde81d7f904116" + integrity sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g== + prompts@^2.0.1: version "2.3.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068" @@ -8487,6 +8555,19 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +sinon@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.2.0.tgz#1d333967e30023609f7347351ebc0dc964c0f3c9" + integrity sha512-eSNXz1XMcGEMHw08NJXSyTHIu6qTCOiN8x9ODACmZpNQpr0aXTBXBnI4xTzQzR+TEpOmLiKowGf9flCuKIzsbw== + dependencies: + "@sinonjs/commons" "^1.8.1" + "@sinonjs/fake-timers" "^6.0.1" + "@sinonjs/formatio" "^5.0.1" + "@sinonjs/samsam" "^5.2.0" + diff "^4.0.2" + nise "^4.0.4" + supports-color "^7.1.0" + sisteransi@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -9306,7 +9387,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@4.0.8: +type-detect@4.0.8, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==