@carbon/ibm-cloud-cognitive-cdai
Version:
Carbon for Cloud & Cognitive CD&AI UI components
659 lines (654 loc) • 23.2 kB
JavaScript
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import _regeneratorRuntime from "@babel/runtime/regenerator";
//
// Copyright IBM Corp. 2020, 2020
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//
import { IdeImporting } from '.';
import { countFiles, sortFiles, FILE_UPLOAD_STATUS, validateFileAdded } from './helpers';
import { FileUploaderItem, TextInput } from 'carbon-components-react';
import { waitFor } from '@testing-library/react';
import React from 'react';
// import {act} from 'react-dom/test-utils';
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import sleep from '../../component_helpers/sleep';
configure({
adapter: new Adapter()
});
describe('IdeImporting unit tests', function () {
it('should render correct contents (both url and file)', function () {
var mockHandleFileAdded = jest.fn();
var props = {
enableFileDrop: false,
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
};
var wrapper = new IdeImportingWrapper(props);
wrapper.unmount();
});
it('should render correct contents (file only)', function () {
var mockHandleFileAdded = jest.fn();
var props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded,
enableUrlInput: false
};
var wrapper = new IdeImportingWrapper(props);
wrapper.unmount();
});
it('should render correct contents (url only)', function () {
var mockHandleFileAdded = jest.fn();
var props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded,
enableFile: false
};
var wrapper = new IdeImportingWrapper(props);
wrapper.unmount();
});
it('should handle adding a file via drop', function () {
var mockHandleFileAdded = jest.fn();
var props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
};
var wrapper = new IdeImportingWrapper(props);
wrapper.simulateDropFiles([{
name: 'test-file.png'
}]);
wrapper.expectPropCalled('onFileAdded');
});
it('should handle adding a file via drop (single)', function () {
var mockHandleFileAdded = jest.fn();
var props = {
multiple: false,
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
};
var wrapper = new IdeImportingWrapper(props);
wrapper.simulateDropFiles([{
name: 'test-file.png'
}]);
wrapper.expectPropCalled('onFileAdded');
});
it('should hide the file drop area after uploading a single file', function () {
var mockHandleFileAdded = jest.fn();
var props = {
multiple: false,
validExtensions: ['png'],
hideImport: true,
onFileAdded: mockHandleFileAdded
};
var wrapper = new IdeImportingWrapper(props);
var errorMessage = new Error('FileUploaderDropContainer not found when using strictFind()');
wrapper.simulateDropFiles([{
name: 'test-file.png'
}]);
wrapper.expectPropCalled('onFileAdded');
expect(function () {
wrapper.strictFind('FileUploaderDropContainer');
}).toThrow(errorMessage);
wrapper.unmount();
});
it('should handle an initial state value', function () {
var mockHandleFileAdded = jest.fn();
var props = {
multiple: false,
validExtensions: ['yml'],
hideImport: true,
onFileAdded: mockHandleFileAdded,
initialFiles: [{
file: {
lastModified: 1606086665265,
lastModifiedDate: 'Sun Nov 22 2020 23:11:05 GMT+0000 (Greenwich Mean Time)',
name: 'accounts',
size: 702,
type: 'application/x-yaml',
webkitRelativePath: '',
index: 0
},
invalid: false,
status: 'edit',
url: undefined,
uuid: 'b4a92c13-10ca'
}]
};
var wrapper = new IdeImportingWrapper(props);
var errorMessage = new Error('FileUploaderDropContainer not found when using strictFind()');
expect(function () {
wrapper.strictFind('FileUploaderDropContainer');
}).toThrow(errorMessage);
wrapper.unmount();
});
it('should disable the file drop as soon as there is text in the URL field (single)', function () {
var mockHandleFileAdded = jest.fn();
var props = {
multiple: false,
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
};
var wrapper = new IdeImportingWrapper(props);
wrapper.changeUrl('http://valid.com/image.png');
expect(wrapper.strictFind('FileUploaderDropContainer').prop('disabled')).toBe(true);
wrapper.unmount();
});
it('should handle errors thrown by onFileAdded', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var warn, props, wrapper;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
warn = jest.spyOn(console, 'warn').mockImplementation(function () {});
props = {
validExtensions: ['png'],
onFileAdded: jest.fn(function () {
throw new Error('Subject: message');
})
};
wrapper = new IdeImportingWrapper(props);
wrapper.simulateDropFiles([{
name: 'test-file.png'
}]);
expect(props.onFileAdded).toBeCalled();
expect(props.onFileAdded).toThrow();
_context.next = 8;
return waitFor(function () {
expect(warn).toBeCalledWith(expect.objectContaining({
message: 'Subject: message'
}));
});
case 8:
wrapper.unmount();
warn.mockRestore();
case 10:
case "end":
return _context.stop();
}
}, _callee);
})));
it('should handle removing a file', function () {
var mockHandleFileAdded = jest.fn();
var props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
};
var wrapper = new IdeImportingWrapper(props);
wrapper.simulateDropFiles([{
name: 'test-file.png'
}]);
wrapper.expectPropCalled('onFileAdded');
wrapper.removeFirstFile();
wrapper.expectNoFiles();
});
it('should call onFileRemoved when removing a file if supplied', function () {
var mockHandleFileAdded = jest.fn();
var mockHandleFileRemoved = jest.fn();
var props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded,
onFileRemoved: mockHandleFileRemoved
};
var wrapper = new IdeImportingWrapper(props);
wrapper.simulateDropFiles([{
name: 'test-file.png'
}]);
wrapper.expectPropCalled('onFileAdded');
wrapper.removeFirstFile();
wrapper.expectPropCalled('onFileRemoved');
wrapper.expectNoFiles();
});
it('should handle adding a file larger than the max size via drop', function () {
var mockHandleFileAdded = jest.fn();
var props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded,
maxFileSize: 100
};
var wrapper = new IdeImportingWrapper(props);
wrapper.simulateDropFiles([{
name: 'test-file.png',
size: 200
}]);
expect(mockHandleFileAdded).not.toBeCalled();
wrapper.unmount();
});
it('should handle adding a file with no extension via drop', function () {
var mockHandleFileAdded = jest.fn();
var props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded,
extensionRequired: true
};
var wrapper = new IdeImportingWrapper(props);
wrapper.simulateDropFiles([{
name: 'test-file'
}]);
expect(mockHandleFileAdded).not.toBeCalled();
wrapper.unmount();
});
it('should handle adding a file with an invalid file name via drop', function () {
var mockHandleFileAdded = jest.fn();
var props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
};
var wrapper = new IdeImportingWrapper(props);
wrapper.addFileViaUrl('****');
expect(mockHandleFileAdded).not.toBeCalled();
wrapper.unmount();
});
it('should handle adding a file via url', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
var mockHandleFileAdded, props, wrapper;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
mockHandleFileAdded = jest.fn();
props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
};
wrapper = new IdeImportingWrapper(props);
wrapper.addFileViaUrl('http://valid.com/image.png');
wrapper.expectPropCalled('onFileAdded');
case 5:
case "end":
return _context2.stop();
}
}, _callee2);
})));
it('should handle custom url validation', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
var mockHandleFileAdded, props, wrapper;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
mockHandleFileAdded = jest.fn();
props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded,
onValidateUrl: jest.fn(function () {
return true;
})
};
wrapper = new IdeImportingWrapper(props);
wrapper.addFileViaUrl('http://valid.com/image.png');
wrapper.expectPropCalled('onFileAdded');
wrapper.expectPropCalled('onValidateUrl');
case 6:
case "end":
return _context3.stop();
}
}, _callee3);
})));
it('should handle invalid url extensions', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
var mockHandleFileAdded, props, wrapper;
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
mockHandleFileAdded = jest.fn();
props = {
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
};
wrapper = new IdeImportingWrapper(props);
wrapper.addFileViaUrl('http://valid.com/image.notvalid');
expect(mockHandleFileAdded).not.toBeCalled();
wrapper.unmount();
case 6:
case "end":
return _context4.stop();
}
}, _callee4);
})));
it('should allow invalid url extensions when enabled', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
var mockHandleFileAdded, props, wrapper;
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) switch (_context5.prev = _context5.next) {
case 0:
mockHandleFileAdded = jest.fn();
props = {
validExtensions: ['png'],
allowInvalidFilenameInUrl: true,
onFileAdded: mockHandleFileAdded
};
wrapper = new IdeImportingWrapper(props);
wrapper.addFileViaUrl('http://valid.com/image.notvalid');
expect(mockHandleFileAdded).toBeCalled();
case 5:
case "end":
return _context5.stop();
}
}, _callee5);
})));
it('should handle invalid url extensions plural', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6() {
var mockHandleFileAdded, props, wrapper;
return _regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) switch (_context6.prev = _context6.next) {
case 0:
mockHandleFileAdded = jest.fn();
props = {
validExtensions: ['yml', 'yaml'],
onFileAdded: mockHandleFileAdded
};
wrapper = new IdeImportingWrapper(props);
wrapper.addFileViaUrl('http://valid.com/image.notvalid');
expect(mockHandleFileAdded).not.toBeCalled();
wrapper.unmount();
case 6:
case "end":
return _context6.stop();
}
}, _callee6);
})));
it('should allow for FileUploaderItem to call onDelete', function () {
var mockHandleFileAdded = jest.fn();
var props = {
enableUpload: false,
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
};
var wrapper = new IdeImportingWrapper(props);
wrapper.dropAFewPngFiles();
wrapper.simulateDeleteFile();
});
describe('countFiles', function () {
it('should return the correct counts for empty set', function () {
var files = [];
var counts = countFiles(files);
expect(counts).toHaveProperty('finished', 0);
expect(counts).toHaveProperty('uploading', 0);
expect(counts).toHaveProperty('invalid', 0);
expect(counts).toHaveProperty('total', 0);
});
it('should return the correct counts for invalid set', function () {
var files = [{
invalid: true
}];
var counts = countFiles(files);
expect(counts).toHaveProperty('finished', 0);
expect(counts).toHaveProperty('uploading', 0);
expect(counts).toHaveProperty('invalid', 1);
expect(counts).toHaveProperty('total', 1);
});
});
describe('sortFiles', function () {
it('should ensure error files are first', function () {
var files = [{
index: 0,
status: FILE_UPLOAD_STATUS.COMPLETE
}, {
index: 1,
status: FILE_UPLOAD_STATUS.EDIT
}, {
index: 2,
status: FILE_UPLOAD_STATUS.UPLOADING
}];
var sorted = files.sort(function (a, b) {
return sortFiles(a, b, files.length);
});
expect(sorted[0]).toHaveProperty('status', FILE_UPLOAD_STATUS.EDIT);
});
it('should ensure invalid files are sorted', function () {
var files = [{
index: 1,
status: FILE_UPLOAD_STATUS.UPLOADING
}, {
index: 0,
status: FILE_UPLOAD_STATUS.EDIT,
invalid: true
}, {
index: 2,
status: FILE_UPLOAD_STATUS.UPLOADING
}];
var sorted = files.sort(function (a, b) {
return sortFiles(a, b, files.length);
});
expect(sorted[0]).toHaveProperty('status', FILE_UPLOAD_STATUS.EDIT);
});
it('should handle two matching files', function () {
var files = [{
index: 1,
status: FILE_UPLOAD_STATUS.UPLOADING
}, {
index: 0,
status: FILE_UPLOAD_STATUS.EDIT
}, {
index: 1,
status: FILE_UPLOAD_STATUS.UPLOADING
}];
var sorted = files.sort(function (a, b) {
return sortFiles(a, b, files.length);
});
expect(sorted[0]).toHaveProperty('status', FILE_UPLOAD_STATUS.EDIT);
});
});
describe('validateFileAdded', function () {
it('should validate the file added', function () {
var props = {
validExtensions: ['png']
};
var testFile = {
file: {
size: 1000,
name: 'foo.png'
}
};
var result = validateFileAdded(testFile, props, jest.fn());
expect(result).toHaveProperty('invalid', false);
});
it('should validate filename', function () {
var props = {
validExtensions: ['png']
};
var testFile = {
file: {
size: 1000,
name: '*'
}
};
var result = validateFileAdded(testFile, props, jest.fn());
expect(result).toHaveProperty('invalid', true);
});
});
describe('text props', function () {
it('should allow overriding all text props', function () {
var customTextProps = {
verbLabel: 'CUSTOM',
uploadDescription: 'CUSTOM Use the inputs below to select file(s) to be uploaded.',
importDescription: 'CUSTOM Use the inputs below to select file(s) to be imported.',
headingPlural: 'CUSTOM Select Files to import',
headingSingular: 'CUSTOM Select a File import',
fileTabLabel: 'CUSTOM File',
urlTabLabel: 'CUSTOM URL',
invalidFileNameText: 'CUSTOM You must provide a valid file name.',
fileDropLabelSingular: 'CUSTOM Drag and drop a single file here or click to import',
fileDropLabelPlural: 'CUSTOM Drag and drop files here or click to import',
filenameRequiredText: 'CUSTOM A filename is required.',
invalidUrlText: 'CUSTOM Enter a valid URL',
maxFileSizeSubject: 'CUSTOM File size exceeds limit',
maxFileSizeMessage: 'CUSTOM File is larger than the max file size.',
addUrlBttonLabel: 'CUSTOM Add File',
extensionIsRequiredText: 'CUSTOM File must have a valid extension.',
extensionIsInvalidText: 'CUSTOM Extension is not valid.',
errorTextSingular: 'CUSTOM Failed to import file.',
errorTextPlural: 'CUSTOM Failed to import files.',
successTextSingular: 'CUSTOM Your file has been imported.',
successTextPlural: 'CUSTOM Your files have been imported.',
invalidFileText: 'CUSTOM Invalid File',
mustBeExtensionTextSingular: 'CUSTOM Must be a $EXT file.',
mustBeExtensionTextPlural: 'CUSTOM Must be one of: $EXT.',
defaultUncaughtErrorSubject: 'CUSTOM Import Failed',
defaultUncaughtErrorBody: 'CUSTOM Failed to import file.',
filesToUploadTextPlural: 'CUSTOM Files to import',
filesToUploadTextSingular: 'CUSTOM File to import',
fileDropHeader: 'CUSTOM Add by File',
urlInputHeader: 'CUSTOM Add by URL'
};
function testCustomTextProps() {
var customProps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var mockHandleFileAdded = jest.fn();
var props = _objectSpread(_objectSpread({
validExtensions: ['png'],
onFileAdded: mockHandleFileAdded
}, customTextProps), customProps);
var wrapper = new IdeImportingWrapper(props);
wrapper.dropAFewPngFiles();
}
// simple override
testCustomTextProps();
// enableUpload
testCustomTextProps({
enableUpload: true
});
// default import text
testCustomTextProps({
enableUpload: false,
verbLabel: undefined
});
});
});
});
// This should eventually be used to implement
// the gherkin rules
var IdeImportingWrapper = /*#__PURE__*/function () {
function IdeImportingWrapper(props) {
_classCallCheck(this, IdeImportingWrapper);
this.props = props;
this.wrapper = mount(/*#__PURE__*/React.createElement(IdeImporting, props));
}
return _createClass(IdeImportingWrapper, [{
key: "unmount",
value: function unmount() {
return this.wrapper.unmount();
}
}, {
key: "resolveAsync",
value: function () {
var _resolveAsync = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee7() {
return _regeneratorRuntime.wrap(function _callee7$(_context7) {
while (1) switch (_context7.prev = _context7.next) {
case 0:
_context7.next = 2;
return sleep(1);
case 2:
// force a re-render
// see https://airbnb.io/enzyme/docs/api/ReactWrapper/update.html
this.wrapper.update();
case 3:
case "end":
return _context7.stop();
}
}, _callee7, this);
}));
function resolveAsync() {
return _resolveAsync.apply(this, arguments);
}
return resolveAsync;
}()
}, {
key: "strictFind",
value: function strictFind(selector) {
var found = this.wrapper.find(selector);
if (found.length === 0) {
var name = typeof selector === 'string' ? selector : selector.name;
throw new Error("".concat(name, " not found when using strictFind()"));
}
return found;
}
}, {
key: "findFilenameInput",
value: function findFilenameInput() {
return this.strictFind(TextInput).find('input');
}
}, {
key: "clickButton",
value: function clickButton(selector) {
var button = this.strictFind(selector);
button.simulate('click');
}
}, {
key: "changeValue",
value: function changeValue(selector, value) {
var target = this.strictFind(selector);
target.simulate('change', {
target: {
value: value
}
});
}
}, {
key: "expectPropCalled",
value: function expectPropCalled(name) {
expect(this.props[name]).toBeCalled();
}
}, {
key: "changeFilename",
value: function changeFilename(value) {
var input = this.findFilenameInput();
input.simulate('change', {
target: {
value: value
}
});
}
}, {
key: "hasFilename",
value: function hasFilename(value) {
return this.findFilenameInput().prop('value') === value;
}
}, {
key: "changeUrl",
value: function changeUrl(url) {
this.changeValue('.ide-importing-flex-input input', url);
}
}, {
key: "addFileViaUrl",
value: function addFileViaUrl(url) {
this.changeUrl(url);
this.clickButton('.ide-importing-flex-button button');
}
}, {
key: "simulateDropFiles",
value: function simulateDropFiles(files) {
var e = {
stopPropagation: jest.fn()
};
this.wrapper.instance().handleFilesAdded(e, {
addedFiles: files
});
this.wrapper.update();
}
}, {
key: "dropAFewPngFiles",
value: function dropAFewPngFiles() {
this.simulateDropFiles([{
name: 'foo.png'
}, {
name: 'bar.png'
}]);
}
}, {
key: "removeFirstFile",
value: function removeFirstFile() {
var inst = this.wrapper.instance();
var firstFile = inst.state.filesToUpload[0];
inst.handleRemoveFile(firstFile.uuid);
}
}, {
key: "expectNoFiles",
value: function expectNoFiles() {
expect(this.wrapper.instance().state.filesToUpload).toHaveLength(0);
}
}, {
key: "simulateDeleteFile",
value: function simulateDeleteFile() {
this.strictFind(FileUploaderItem).first().invoke('onDelete');
}
}]);
}();