Bring React into the tree, and add linting and bundling framework for the JS etc.

This commit is contained in:
Shruti B Iyer
2017-06-12 16:51:54 +01:00
committed by Dave Page
parent af43ccfc07
commit 659eb1c1e8
32 changed files with 6680 additions and 1840 deletions

1
.gitignore vendored
View File

@@ -37,3 +37,4 @@ runtime/ui_BrowserWindow.h
web/config_local.py
web/regression/test_config.json
node_modules/
web/pgAdmin/static/js/generated

View File

@@ -164,6 +164,12 @@ REM Main function Ends
CD "%WD%\web"
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
ECHO Install Javascript dependencies
yarn install
ECHO Bundle all Javascript
yarn run bundle
XCOPY /S /I /E /H /Y "%WD%\web" "%PGBUILDPATH%\web" > nul
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%

View File

@@ -238,6 +238,12 @@ REM Main function Ends
CD "%WD%\web"
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
ECHO Install Javascript dependencies
yarn install
ECHO Bundle all Javascript
yarn run bundle
XCOPY /S /I /E /H /Y "%WD%\web" "%PGBUILDPATH%\web" > nul
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%

View File

@@ -178,6 +178,11 @@ _complete_bundle() {
# run complete-bundle to copy the dependent libraries and frameworks and fix the rpaths
./complete-bundle.sh "$BUILDROOT/$APP_BUNDLE_NAME" || { echo complete-bundle.sh failed; exit 1; }
pushd $SOURCEDIR/web
yarn install
yarn run bundle
popd
# copy the web directory to the bundle as it is required by runtime
cp -r $SOURCEDIR/web "$BUILDROOT/$APP_BUNDLE_NAME/Contents/Resources/" || exit 1
cd "$BUILDROOT/$APP_BUNDLE_NAME/Contents/Resources/web"

View File

@@ -57,6 +57,15 @@ do
tar cf - $FILE | (cd ../pip-build/pgadmin4; tar xf -)
done
yarn install
yarn run bundle
for FILE in `ls -d pgAdmin/static/js/generated/*`
do
echo Adding $FILE
tar cf - $FILE | (cd ../pip-build/pgadmin4; tar xf -)
done
cd ../docs
for FILE in `git ls-files`
do

View File

@@ -69,6 +69,17 @@ do
tar cf - $FILE | (cd src-build/$TARBALL_NAME; tar xf -)
done
pushd web
yarn install
yarn run bundle
for FILE in `ls -d pgAdmin/static/js/generated/*`
do
echo Adding $FILE
tar cf - $FILE | (cd ../src-build/$TARBALL_NAME/web; tar xf -)
done
popd
# Create the tarball
echo Creating tarball...
cd src-build

View File

@@ -1,28 +1,23 @@
// Karma configuration
// Generated on Wed Mar 01 2017 14:19:28 GMT-0500 (EST)
const webpackConfig = require('./webpack.test.config.js');
module.exports = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine', 'requirejs'],
// list of files / patterns to load in the browser
files: [
'regression/javascript/test-main.js',
{pattern: 'regression/javascript/**/*.js', included: false},
{pattern: 'pgadmin/static/vendor/**/*.js', included: false},
{pattern: 'pgadmin/static/js/**/*.js', included: false},
{pattern: 'pgadmin/browser/static/js/**/*.js', included: false},
{pattern: 'pgadmin/static/img/*.png', included: false}
frameworks: ['jasmine'],
plugins: [
'karma-webpack',
'karma-phantomjs-launcher',
'karma-jasmine',
'karma-jasmine-html-reporter',
],
files: [
{pattern: 'pgadmin/static/**/*.js', included: false},
{pattern: 'pgadmin/static/vendor/**/*.js', included: false},
{pattern: 'pgadmin/browser/static/js/**/*.js', included: false},
'regression/javascript/**/*.jsx',
'regression/javascript/**/*.js',
],
// list of files to exclude
exclude: [
@@ -30,34 +25,30 @@ module.exports = function(config) {
'pgadmin/static/vendor/**/*[Ss]pec.js'
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'regression/javascript/**/*.js': ['webpack'],
// 'regression/javascript/**/*.jsx': ['webpack'],
},
webpack: webpackConfig,
webpackMiddleware: {
stats: 'errors-only',
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
logLevel: config.LOG_WARN,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
autoWatch: true,
// start these browsers
@@ -67,10 +58,10 @@ module.exports = function(config) {
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
});
};

View File

@@ -1,10 +1,43 @@
{
"devDependencies": {
"jasmine-core": "^2.5.2",
"karma": "^1.5.0",
"karma-jasmine": "^1.1.0",
"karma-phantomjs-launcher": "^1.0.2",
"karma-requirejs": "^1.1.0",
"requirejs": "^2.3.3"
"babel-core": "~6.24.0",
"babel-loader": "~6.4.1",
"babel-preset-es2015": "~6.24.0",
"babel-preset-react": "~6.23.0",
"enzyme": "~2.8.2",
"jasmine-core": "~2.5.2",
"karma": "~1.5.0",
"karma-babel-preprocessor": "^6.0.1",
"karma-browserify": "~5.1.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "~0.2.2",
"karma-phantomjs-launcher": "~1.0.2",
"karma-requirejs": "~1.1.0",
"karma-sourcemap-loader": "~0.3.7",
"karma-webpack": "~2.0.3",
"react-addons-test-utils": "~15.4.2",
"webpack": "~2.3.1"
},
"dependencies": {
"axios": "^0.16.1",
"babel-plugin-transform-es2015-modules-amd": "^6.24.1",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015-without-strict": "~0.0.4",
"babelify": "~7.3.0",
"browserify": "~14.1.0",
"exports-loader": "~0.6.4",
"imports-loader": "git+https://github.com/webpack-contrib/imports-loader.git#44d6f48463b256a17c1ba6fd9b5cc1449b4e379d",
"react": "~15.4.2",
"react-dom": "~15.4.2",
"requirejs": "~2.3.3",
"underscore": "~1.8.3",
"watchify": "~3.9.0"
},
"scripts": {
"bundle": "yarn run webpack -- --optimize-minimize --config webpack.config.js",
"test:karma-once": "yarn run karma start -- --single-run",
"test:karma": "yarn run karma start",
"test:feature": "yarn run bundle && python regression/runtests.py --pkg feature_tests",
"test": "yarn run test:karma-once && yarn run bundle && python regression/runtests.py"
}
}

View File

@@ -22,17 +22,36 @@ if sys.path[0] != root:
import config
from pgadmin import create_app
from pgadmin.utils import u, fs_encoding, file_quote
if config.DEBUG:
from pgadmin.utils.javascript.javascript_bundler import JavascriptBundler, JsState
# Get the config database schema version. We store this in pgadmin.model
# as it turns out that putting it in the config files isn't a great idea
from pgadmin.model import SCHEMA_VERSION
config.SETTINGS_SCHEMA_VERSION = SCHEMA_VERSION
##########################################################################
# Sanity checks
##########################################################################
# Check if the database exists. If it does not, create it.
if not os.path.isfile(config.SQLITE_PATH):
setupfile = os.path.join(
os.path.dirname(os.path.realpath(u(__file__, fs_encoding))), u'setup.py'
)
exec(open(file_quote(setupfile), 'r').read())
##########################################################################
# Server starup
# Server startup
##########################################################################
# Build Javascript files
if config.DEBUG:
javascriptBundler = JavascriptBundler()
javascriptBundler.bundle()
# Create the app!
app = create_app()
@@ -41,6 +60,13 @@ if config.DEBUG:
else:
app.debug = False
# respond to JS
if config.DEBUG:
if javascriptBundler.report() == JsState.NONE:
app.logger.error("Unable to generate javascript")
app.logger.error("To run the app ensure that yarn install command runs successfully")
raise Exception("No generated javascript, aborting")
# Start the web server. The port number should have already been set by the
# runtime if we're running in desktop mode, otherwise we'll just use the
# Flask default.

View File

@@ -0,0 +1,8 @@
import React from 'react';
import {render} from 'react-dom';
export {
render,
React,
};

View File

@@ -0,0 +1,8 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2017, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
###########################################################################

View File

@@ -0,0 +1,62 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2017, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
import os
from contextlib import contextmanager
from subprocess import call
from pgadmin.utils import u, fs_encoding, file_quote
# enum-like for tracking whether we have
class JsState:
NONE = 0
OLD = 1
NEW = 2
class JavascriptBundler:
"""Builds Javascript bundle files by delegating to webpack"""
def __init__(self):
self.jsState = JsState.NONE
def bundle(self):
try:
try_building_js()
self.jsState = JsState.NEW
except OSError:
webdir_path()
generatedJavascriptDir = os.path.join(webdir_path(), 'pgadmin', 'static', 'js', 'generated')
if os.path.exists(generatedJavascriptDir) and os.listdir(generatedJavascriptDir):
self.jsState = JsState.OLD
else:
self.jsState = JsState.NONE
def report(self):
return self.jsState
@contextmanager
def pushd(new_dir):
previous_dir = os.getcwd()
os.chdir(new_dir)
yield
os.chdir(previous_dir)
def webdir_path():
dirname = os.path.dirname
thisPath = os.path.realpath(u(__file__, fs_encoding))
return dirname(dirname(dirname(dirname(thisPath))))
def try_building_js():
with pushd(webdir_path()):
if call(['yarn', 'run', 'bundle']) != 0:
raise OSError('Error executing bundling the application')

View File

@@ -0,0 +1,8 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2017, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
###########################################################################

View File

@@ -0,0 +1,117 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2017, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
import sys
from pgadmin.utils.route import BaseTestGenerator
if sys.version_info < (3, 3):
import mock
else:
import unittest.mock as mock
class JavascriptBundlerTestCase(BaseTestGenerator):
"""This tests that the javascript bundler tool causes the application to bundle,
and can be invoked before and after app start correctly"""
scenarios = [('scenario name: JavascriptBundlerTestCase', dict())]
def setUp(self):
self.mockSubprocess = mock.Mock()
self.mockOs = mock.Mock()
sys.modules['subprocess'] = self.mockSubprocess
sys.modules['os'] = self.mockOs
def runTest(self):
from pgadmin.utils.javascript.javascript_bundler import JavascriptBundler
from pgadmin.utils.javascript.javascript_bundler import JsState
self.JavascriptBundler = JavascriptBundler
self.JsState = JsState
self._bundling_succeeds()
self.resetTestState()
self._bundling_fails_and_there_is_no_existing_bundle()
self.resetTestState()
self._bundling_fails_when_bundling_returns_nonzero()
self.resetTestState()
self._bundling_fails_and_there_is_no_existing_bundle_directory()
self.resetTestState()
self._bundling_fails_but_there_was_existing_bundle()
self.resetTestState()
def resetTestState(self):
self.mockSubprocess.reset_mock()
self.mockSubprocess.call.side_effect = None
self.mockOs.reset_mock()
self.mockOs.listdir.side_effect = None
self.mockOs.path.exists.side_effect = None
def _bundling_succeeds(self):
javascriptBundler = self.JavascriptBundler()
self.assertEqual(len(self.mockSubprocess.method_calls), 0)
self.mockSubprocess.call.return_value = 0
self.mockOs.listdir.return_value = [u'history.js', u'reactComponents.js']
javascriptBundler.bundle()
self.mockSubprocess.call.assert_called_once_with(['yarn', 'run', 'bundle'])
reportedState = javascriptBundler.report()
expectedState = self.JsState.NEW
self.assertEqual(reportedState, expectedState)
def _bundling_fails_when_bundling_returns_nonzero(self):
javascriptBundler = self.JavascriptBundler()
self.assertEqual(len(self.mockSubprocess.method_calls), 0)
self.mockOs.listdir.return_value = []
self.mockSubprocess.call.return_value = 99
javascriptBundler.bundle()
reportedState = javascriptBundler.report()
expectedState = self.JsState.NONE
self.assertEqual(reportedState, expectedState)
def _bundling_fails_and_there_is_no_existing_bundle(self):
javascriptBundler = self.JavascriptBundler()
self.mockSubprocess.call.side_effect = OSError("mock exception behavior")
self.mockOs.path.exists.return_value = True
self.mockOs.listdir.return_value = []
javascriptBundler.bundle()
reportedState = javascriptBundler.report()
expectedState = self.JsState.NONE
self.assertEqual(reportedState, expectedState)
def _bundling_fails_and_there_is_no_existing_bundle_directory(self):
javascriptBundler = self.JavascriptBundler()
self.mockSubprocess.call.side_effect = OSError("mock exception behavior")
self.mockOs.path.exists.return_value = False
self.mockOs.listdir.side_effect = OSError("mock exception behavior")
javascriptBundler.bundle()
reportedState = javascriptBundler.report()
expectedState = self.JsState.NONE
self.assertEqual(reportedState, expectedState)
def _bundling_fails_but_there_was_existing_bundle(self):
javascriptBundler = self.JavascriptBundler()
self.mockSubprocess.call.side_effect = OSError("mock exception behavior")
self.mockOs.path.exists.return_value = True
self.mockOs.listdir.return_value = [u'history.js', u'reactComponents.js']
javascriptBundler.bundle()
self.mockSubprocess.call.assert_called_once_with(['yarn', 'run', 'bundle'])
reportedState = javascriptBundler.report()
expectedState = self.JsState.OLD
self.assertEqual(reportedState, expectedState)

View File

@@ -177,16 +177,17 @@ Javascript Tests:
sudo port install nodejs7 yarn
- See also the top-level pgadmin/README : Bundling Javascript
- Javascript tests must be run from the web directory (since that is where node_modules and karma.conf reside):
cd web/
- Install the JS modules required for testing:
yarn
yarn install
- Now run the tests:
yarn run karma start --single-run
yarn run test:karma
yarn run test:karma-once

View File

@@ -7,9 +7,11 @@
//
//////////////////////////////////////////////////////////////
define(["browser/menu"
], function () {
describe("MenuItem", function () {
define([
'pgadmin',
'browser/menu',
], function (pgAdmin) {
describe('MenuItem', function () {
var MenuItem = pgAdmin.Browser.MenuItem;
var menuItem;

View File

@@ -7,45 +7,46 @@
//
//////////////////////////////////////////////////////////////////////////
define(["sources/gettext", "translations"], function (gettext, translations) {
describe("translate", function () {
describe("when there is no translation", function () {
it("returns the original string", function () {
expect(gettext("something to be translated")).toEqual("something to be translated");
import gettext from 'sources/gettext';
import translations from 'translations';
describe('translate', function () {
describe('when there is no translation', function () {
it('returns the original string', function () {
expect(gettext('something to be translated')).toEqual('something to be translated');
});
describe("when there are substitutions", function () {
it("interpolates a substitution", function () {
expect(gettext("translate text for %(person)s", {"person": "Sarah"})).toEqual("translate text for Sarah")
describe('when there are substitutions', function () {
it('interpolates a substitution', function () {
expect(gettext('translate text for %(person)s', {'person': 'Sarah'})).toEqual('translate text for Sarah');
});
it("interpolates multiple substitutions", function () {
expect(gettext("translate '%(text)s' for %(person)s",
it('interpolates multiple substitutions', function () {
expect(gettext('translate \'%(text)s\' for %(person)s',
{
"text": "constitution",
"person": "Sarah"
'text': 'constitution',
'person': 'Sarah',
}
)).toEqual("translate 'constitution' for Sarah")
)).toEqual('translate \'constitution\' for Sarah');
});
});
});
describe("when there is a translation", function () {
describe('when there is a translation', function () {
beforeEach(function () {
translations['something to be translated'] = 'etwas zum uebersetzen';
translations['another translation for %(person)s'] = 'eine weitere Uebersetzung fuer %(person)s';
});
it("returns the translation", function () {
expect(gettext("something to be translated")).toEqual("etwas zum uebersetzen");
it('returns the translation', function () {
expect(gettext('something to be translated')).toEqual('etwas zum uebersetzen');
});
describe("when there is a substitution", function () {
it("interpolates the substitution", function () {
expect(gettext("another translation for %(person)s", {"person": "Sarah"}))
.toEqual("eine weitere Uebersetzung fuer Sarah");
});
describe('when there is a substitution', function () {
it('interpolates the substitution', function () {
expect(gettext('another translation for %(person)s', {'person': 'Sarah'}))
.toEqual('eine weitere Uebersetzung fuer Sarah');
});
});
});

View File

@@ -0,0 +1,23 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
/* eslint-disable no-console */
beforeAll(function () {
spyOn(console, 'warn').and.callThrough();
spyOn(console, 'error').and.callThrough();
});
afterEach(function (done) {
setTimeout(function () {
expect(console.warn).not.toHaveBeenCalled();
expect(console.error).not.toHaveBeenCalled();
done();
}, 0);
});

View File

@@ -1,29 +1,34 @@
define(
["jquery",
"underscore",
"sources/selection/column_selector",
"sources/selection/active_cell_capture",
"sources/selection/grid_selector",
'sources/selection/xcell_selection_model',
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
"slickgrid",
'sources/slickgrid/pgslick.cellrangedecorator',
'sources/slickgrid/pgslick.cellrangeselector',
"slickgrid/slick.grid",
],
function ($, _, ColumnSelector, ActiveCellCapture, GridSelector, XCellSelectionModel) {
import $ from 'jquery';
import Slick from 'slickgrid';
import 'slickgrid.grid';
import ColumnSelector from 'sources/selection/column_selector';
import ActiveCellCapture from 'sources/selection/active_cell_capture';
import 'sources/selection/grid_selector';
import XCellSelectionModel from 'sources/selection/xcell_selection_model';
import 'sources/slickgrid/pgslick.cellrangedecorator';
import 'sources/slickgrid/pgslick.cellrangeselector';
describe('ColumnSelector', function () {
var container, data, columns, options;
var SlickGrid = Slick.Grid;
var KEY_RIGHT = 39;
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_DOWN = 40;
var Slick = window.Slick;
var SlickGrid = Slick.Grid;
describe("ColumnSelector", function () {
var container, data, columns, options;
beforeEach(function () {
container = $("<div></div>");
container = $('<div></div>');
container.height(9999);
container.width(9999);
@@ -76,7 +81,7 @@ define(
];
});
it("displays the name of the column", function () {
it('displays the name of the column', function () {
setupGrid(columns);
expect($(container.find('.slick-header-columns .slick-column-name')[1]).text())
@@ -89,14 +94,14 @@ define(
.toContain('json');
});
it("preserves the other attributes of column definitions", function () {
it('preserves the other attributes of column definitions', function () {
var columnSelector = new ColumnSelector();
var selectableColumns = columnSelector.getColumnDefinitions(columns);
expect(selectableColumns[1].id).toBe('1');
});
describe("with ActiveCellCapture, CellSelectionModel, and GridSelector: selecting columns", function () {
describe('with ActiveCellCapture, CellSelectionModel, and GridSelector: selecting columns', function () {
var grid, cellSelectionModel;
beforeEach(function () {
var columnSelector = new ColumnSelector();
@@ -118,21 +123,21 @@ define(
grid.registerPlugin(columnSelector);
grid.invalidate();
$("body").append(container);
$('body').append(container);
});
afterEach(function () {
$("body").find(container).remove();
$('body').find(container).remove();
});
describe("when the user clicks a column header", function () {
it("selects the column", function () {
describe('when the user clicks a column header', function () {
it('selects the column', function () {
container.find('.slick-header-column:contains(some-column-name)').click();
var selectedRanges = cellSelectionModel.getSelectedRanges();
expectOnlyTheFirstColumnToBeSelected(selectedRanges);
});
it("toggles a selected class to the header cell", function () {
it('toggles a selected class to the header cell', function () {
container.find('.slick-header-column:contains(second column)').click();
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
.toBe(true);
@@ -143,13 +148,13 @@ define(
});
});
describe("when the user clicks an additional column header", function () {
describe('when the user clicks an additional column header', function () {
beforeEach(function () {
container.find('.slick-header-column:contains(some-column-name)').click();
container.find('.slick-header-column:contains(second column)').click();
});
it("selects additional columns", function () {
it('selects additional columns', function () {
var selectedRanges = cellSelectionModel.getSelectedRanges();
@@ -163,16 +168,16 @@ define(
expect(column2.toCell).toBe(2);
});
describe("and presses shift + right-arrow", function () {
describe('and presses shift + right-arrow', function () {
beforeEach(function () {
pressShiftArrow(KEY_RIGHT);
});
it("keeps the last column selected", function () {
it('keeps the last column selected', function () {
expect(cellSelectionModel.getSelectedRanges().length).toBe(1);
});
it("grows the selection to the right", function () {
it('grows the selection to the right', function () {
var selectedRange = cellSelectionModel.getSelectedRanges()[0];
expect(selectedRange.fromCell).toBe(2);
expect(selectedRange.toCell).toBe(3);
@@ -180,7 +185,7 @@ define(
expect(selectedRange.toRow).toBe(9);
});
it("keeps selected class on columns 2 and 3", function () {
it('keeps selected class on columns 2 and 3', function () {
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
.toBe(true);
expect($(container.find('.slick-header-column:contains(third column)')).hasClass('selected'))
@@ -190,13 +195,13 @@ define(
});
});
describe("when the user deselects the last selected column header", function () {
describe('when the user deselects the last selected column header', function () {
beforeEach(function () {
container.find('.slick-header-column:contains(second column)').click();
});
describe("and presses shift + right-arrow", function () {
it("first and second columns are selected", function () {
describe('and presses shift + right-arrow', function () {
it('first and second columns are selected', function () {
pressShiftArrow(KEY_RIGHT);
var selectedRanges = cellSelectionModel.getSelectedRanges();
@@ -211,15 +216,15 @@ define(
});
});
describe("when the user clicks a column header description", function () {
it("selects the column", function () {
describe('when the user clicks a column header description', function () {
it('selects the column', function () {
container.find('.slick-header-columns span.column-description:contains(some-column-name)').click();
var selectedRanges = cellSelectionModel.getSelectedRanges();
expectOnlyTheFirstColumnToBeSelected(selectedRanges);
});
it("toggles a selected class to the header cell", function () {
it('toggles a selected class to the header cell', function () {
container.find('.slick-header-column span.column-description:contains(second column)').click();
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
.toBe(true);
@@ -230,13 +235,13 @@ define(
});
});
describe("when a row is selected", function () {
describe('when a row is selected', function () {
beforeEach(function () {
var selectedRanges = [new Slick.Range(0, 0, 0, 1)];
cellSelectionModel.setSelectedRanges(selectedRanges);
});
it("deselects the row", function () {
it('deselects the row', function () {
container.find('.slick-header-column')[1].click();
var selectedRanges = cellSelectionModel.getSelectedRanges();
@@ -251,12 +256,12 @@ define(
});
});
describe("clicking a second time", function () {
describe('clicking a second time', function () {
beforeEach(function () {
container.find('.slick-header-column')[1].click();
});
it("deselects the column", function () {
it('deselects the column', function () {
container.find('.slick-header-column')[1].click();
var selectedRanges = cellSelectionModel.getSelectedRanges();
@@ -264,8 +269,8 @@ define(
})
});
describe("when the column is not selectable", function () {
it("does not select the column", function () {
describe('when the column is not selectable', function () {
it('does not select the column', function () {
$(container.find('.slick-header-column:contains(some-non-selectable-column)')).click();
var selectedRanges = cellSelectionModel.getSelectedRanges();
@@ -273,12 +278,12 @@ define(
});
});
describe("when the column is deselected through setSelectedRanges", function () {
describe('when the column is deselected through setSelectedRanges', function () {
beforeEach(function () {
container.find('.slick-header-column')[1].click();
});
it("removes selected class from header", function () {
it('removes selected class from header', function () {
cellSelectionModel.setSelectedRanges([]);
expect($(container.find('.slick-header-column')[1]).hasClass('selected'))
@@ -286,13 +291,13 @@ define(
});
});
describe("when a non-column range was already selected", function () {
describe('when a non-column range was already selected', function () {
beforeEach(function () {
var selectedRanges = [new Slick.Range(0, 0, 2, 0)];
cellSelectionModel.setSelectedRanges(selectedRanges);
});
it("deselects the non-column range", function () {
it('deselects the non-column range', function () {
container.find('.slick-header-column:contains(some-column-name)').click();
var selectedRanges = cellSelectionModel.getSelectedRanges();
@@ -349,7 +354,7 @@ define(
expect(column.toRow).toBe(2);
});
it('remove select class on "some-column-name" column header', function () {
it('remove select class on \'some-column-name\' column header', function () {
expect($(container.find('.slick-header-column:contains(some-column-name)')).hasClass('selected'))
.toBeFalsy();
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
@@ -376,7 +381,7 @@ define(
expect(column.toRow).toBe(1);
});
it('no column should have the class "selected"', function () {
it('no column should have the class \'selected\'', function () {
expect($(container.find('.slick-header-column:contains(some-column-name)')).hasClass('selected'))
.toBeFalsy();
});
@@ -407,7 +412,7 @@ define(
}
function pressShiftArrow(keyCode) {
var pressEvent = new $.Event("keydown");
var pressEvent = new $.Event('keydown');
pressEvent.shiftKey = true;
pressEvent.ctrlKey = false;
pressEvent.altKey = false;
@@ -416,4 +421,3 @@ define(
$(container.find('.grid-canvas')).trigger(pressEvent);
}
});
});

View File

@@ -1,28 +1,32 @@
/////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
import $ from 'jquery';
import Slick from 'slickgrid';
import 'slickgrid.grid';
import clipboard from '../../../pgadmin/static/js/selection/clipboard';
import copyData from '../../../pgadmin/static/js/selection/copy_data';
import RangeSelectionHelper from 'sources/selection/range_selection_helper';
import XCellSelectionModel from 'sources/selection/xcell_selection_model';
define(
["jquery",
"slickgrid/slick.grid",
"sources/selection/xcell_selection_model",
"sources/selection/copy_data",
"sources/selection/clipboard",
"sources/selection/range_selection_helper"
],
function ($, SlickGrid, XCellSelectionModel, copyData, clipboard, RangeSelectionHelper) {
describe('copyData', function () {
var grid, sqlEditor, gridContainer, buttonPasteRow;
var Slick, SlickGrid;
beforeEach(function () {
var data = [[1, "leopord", "12"],
[2, "lion", "13"],
[3, "puma", "9"]];
Slick = window.Slick;
SlickGrid = Slick.Grid;
var data = [[1, 'leopord', '12'],
[2, 'lion', '13'],
[3, 'puma', '9']];
var columns = [
{
@@ -33,34 +37,34 @@ define(
column_type: 'text'
},
{
name: "id",
name: 'id',
pos: 0,
label: "id<br> numeric",
cell: "number",
label: 'id<br> numeric',
cell: 'number',
can_edit: false,
type: "numeric"
type: 'numeric'
}, {
name: "brand",
name: 'brand',
pos: 1,
label: "flavor<br> character varying",
cell: "string",
label: 'flavor<br> character varying',
cell: 'string',
can_edit: false,
type: "character varying"
type: 'character varying'
}, {
name: "size",
name: 'size',
pos: 2,
label: "size<br> numeric",
cell: "number",
label: 'size<br> numeric',
cell: 'number',
can_edit: false,
type: "numeric"
type: 'numeric'
}
]
;
gridContainer = $("<div id='grid'></div>");
$("body").append(gridContainer);
buttonPasteRow = $("<button id='btn-paste-row' disabled></button>");
$("body").append(buttonPasteRow);
grid = new Slick.Grid("#grid", data, columns, {});
gridContainer = $('<div id=\'grid\'></div>');
$('body').append(gridContainer);
buttonPasteRow = $('<button id=\'btn-paste-row\' disabled></button>');
$('body').append(buttonPasteRow);
grid = new Slick.Grid('#grid', data, columns, {});
grid.setSelectionModel(new XCellSelectionModel());
sqlEditor = {slickgrid: grid};
});
@@ -70,7 +74,7 @@ define(
buttonPasteRow.remove();
});
describe("when rows are selected", function () {
describe('when rows are selected', function () {
beforeEach(function () {
grid.getSelectionModel().setSelectedRanges([
RangeSelectionHelper.rangeForRow(grid, 0),
@@ -78,7 +82,7 @@ define(
);
});
it("copies them", function () {
it('copies them', function () {
spyOn(clipboard, 'copyTextToClipboard');
copyData.apply(sqlEditor);
@@ -86,26 +90,26 @@ define(
expect(sqlEditor.copied_rows.length).toBe(2);
expect(clipboard.copyTextToClipboard).toHaveBeenCalled();
expect(clipboard.copyTextToClipboard.calls.mostRecent().args[0]).toContain("1,'leopord','12'");
expect(clipboard.copyTextToClipboard.calls.mostRecent().args[0]).toContain("3,'puma','9'");
expect(clipboard.copyTextToClipboard.calls.mostRecent().args[0]).toContain('1,\'leopord\',\'12\'');
expect(clipboard.copyTextToClipboard.calls.mostRecent().args[0]).toContain('3,\'puma\',\'9\'');
});
describe("when the user can edit the grid", function () {
it("enables the paste row button", function () {
describe('when the user can edit the grid', function () {
it('enables the paste row button', function () {
copyData.apply(_.extend({can_edit: true}, sqlEditor));
expect($("#btn-paste-row").prop('disabled')).toBe(false);
expect($('#btn-paste-row').prop('disabled')).toBe(false);
});
});
});
describe("when a column is selected", function () {
describe('when a column is selected', function () {
beforeEach(function () {
var firstDataColumn = RangeSelectionHelper.rangeForColumn(grid, 1);
grid.getSelectionModel().setSelectedRanges([firstDataColumn])
grid.getSelectionModel().setSelectedRanges([firstDataColumn]);
});
it("copies text to the clipboard", function () {
it('copies text to the clipboard', function () {
spyOn(clipboard, 'copyTextToClipboard');
copyData.apply(sqlEditor);
@@ -114,25 +118,24 @@ define(
var copyArg = clipboard.copyTextToClipboard.calls.mostRecent().args[0];
var rowStrings = copyArg.split('\n');
expect(rowStrings[0]).toBe("1");
expect(rowStrings[1]).toBe("2");
expect(rowStrings[2]).toBe("3");
expect(rowStrings[0]).toBe('1');
expect(rowStrings[1]).toBe('2');
expect(rowStrings[2]).toBe('3');
});
it("sets copied_rows to empty", function () {
it('sets copied_rows to empty', function () {
copyData.apply(sqlEditor);
expect(sqlEditor.copied_rows.length).toBe(0);
});
describe("when the user can edit the grid", function () {
describe('when the user can edit the grid', function () {
beforeEach(function () {
copyData.apply(_.extend({can_edit: true}, sqlEditor));
});
it("disables the paste row button", function () {
expect($("#btn-paste-row").prop('disabled')).toBe(true);
});
it('disables the paste row button', function () {
expect($('#btn-paste-row').prop('disabled')).toBe(true);
});
});
});

View File

@@ -1,15 +1,29 @@
define(["jquery",
"underscore",
"slickgrid/slick.grid",
"sources/selection/xcell_selection_model",
"sources/selection/grid_selector"
],
function ($, _, SlickGrid, XCellSelectionModel, GridSelector) {
describe("GridSelector", function () {
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
import $ from 'jquery';
import _ from 'underscore';
import Slick from 'slickgrid';
import 'slickgrid.grid';
import GridSelector from 'sources/selection/grid_selector';
import XCellSelectionModel from 'sources/selection/xcell_selection_model';
describe('GridSelector', function () {
var container, data, columns, gridSelector, xCellSelectionModel;
var Slick, SlickGrid;
beforeEach(function () {
container = $("<div></div>");
Slick = window.Slick;
SlickGrid = Slick.Grid;
container = $('<div></div>');
container.height(9999);
columns = [{
id: '1',
@@ -28,7 +42,7 @@ define(["jquery",
for (var i = 0; i < 10; i++) {
data.push({'some-column-name': 'some-value-' + i, 'second column': 'second value ' + i});
}
var grid = new SlickGrid(container, data, columns);
var grid = new Slick.Grid(container, data, columns);
xCellSelectionModel = new XCellSelectionModel();
grid.setSelectionModel(xCellSelectionModel);
@@ -36,27 +50,27 @@ define(["jquery",
grid.registerPlugin(gridSelector);
grid.invalidate();
$("body").append(container);
$('body').append(container);
});
afterEach(function () {
$("body").find(container).remove();
$('body').find(container).remove();
});
it("renders an additional column on the left for selecting rows", function () {
it('renders an additional column on the left for selecting rows', function () {
expect(columns.length).toBe(3);
var leftmostColumn = columns[0];
expect(leftmostColumn.id).toBe('row-header-column');
});
it("renders a button for selecting all the cells", function () {
expect(container.find("[title='Select/Deselect All']").length).toBe(1);
it('renders a button for selecting all the cells', function () {
expect(container.find('[title=\'Select/Deselect All\']').length).toBe(1);
});
describe("when the cell for the select/deselect all is clicked", function () {
it("selects the whole grid", function () {
container.find("[title='Select/Deselect All']").parent().click();
describe('when the cell for the select/deselect all is clicked', function () {
it('selects the whole grid', function () {
container.find('[title=\'Select/Deselect All\']').parent().click();
var selectedRanges = xCellSelectionModel.getSelectedRanges();
expect(selectedRanges.length).toBe(1);
@@ -67,17 +81,17 @@ define(["jquery",
expect(selectedRange.toRow).toBe(9);
});
it("adds selected class", function () {
container.find("[title='Select/Deselect All']").parent().click();
it('adds selected class', function () {
container.find('[title=\'Select/Deselect All\']').parent().click();
expect($(container.find("[data-id='select-all']")).hasClass('selected')).toBeTruthy();
expect($(container.find('[data-id=\'select-all\']')).hasClass('selected')).toBeTruthy();
});
});
describe("when the select all button in the corner gets selected", function () {
describe('when the select all button in the corner gets selected', function () {
it("selects all the cells", function () {
container.find("[title='Select/Deselect All']").click();
it('selects all the cells', function () {
container.find('[title=\'Select/Deselect All\']').click();
var selectedRanges = xCellSelectionModel.getSelectedRanges();
expect(selectedRanges.length).toBe(1);
@@ -88,29 +102,28 @@ define(["jquery",
expect(selectedRange.toRow).toBe(9);
});
describe("when the select all button in the corner gets deselected", function () {
describe('when the select all button in the corner gets deselected', function () {
beforeEach(function () {
container.find("[title='Select/Deselect All']").click();
container.find('[title=\'Select/Deselect All\']').click();
});
it("deselects all the cells", function () {
container.find("[title='Select/Deselect All']").click();
it('deselects all the cells', function () {
container.find('[title=\'Select/Deselect All\']').click();
var selectedRanges = xCellSelectionModel.getSelectedRanges();
expect(selectedRanges.length).toBe(0);
});
});
describe("and then the underlying selection changes", function () {
describe('and then the underlying selection changes', function () {
beforeEach(function () {
container.find("[title='Select/Deselect All']").click();
container.find('[title=\'Select/Deselect All\']').click();
});
it("removes the selected class", function () {
container.find("[title='Select/Deselect All']").parent().click();
it('removes the selected class', function () {
container.find('[title=\'Select/Deselect All\']').parent().click();
expect($(container.find("[data-id='select-all']")).hasClass('selected')).toBeFalsy();
});
expect($(container.find('[data-id=\'select-all\']')).hasClass('selected')).toBeFalsy();
});
});
});

View File

@@ -1,8 +1,20 @@
define(['sources/selection/range_boundary_navigator'], function (rangeBoundaryNavigator) {
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
describe("#getUnion", function () {
describe("when the ranges completely overlap", function () {
it("returns a list with that range", function () {
import rangeBoundaryNavigator from 'sources/selection/range_boundary_navigator';
import Slick from 'slickgrid';
describe('RangeBoundaryNavigator', function () {
describe('#getUnion', function () {
describe('when the ranges completely overlap', function () {
it('returns a list with that range', function () {
var ranges = [[1, 4], [1, 4], [1, 4]];
var union = rangeBoundaryNavigator.getUnion(ranges);

View File

@@ -1,8 +1,8 @@
define([
'jquery',
'slickgrid/slick.grid',
'sources/selection/range_selection_helper'
], function ($, SlickGrid, RangeSelectionHelper) {
import $ from 'jquery';
import Slick from 'slickgrid';
import 'slickgrid.grid';
import RangeSelectionHelper from 'sources/selection/range_selection_helper';
describe("RangeSelectionHelper utility functions", function () {
var grid;
beforeEach(function () {
@@ -25,7 +25,7 @@ define([
data.push({'some-column-name': 'some-value-' + i, 'second column': 'second value ' + i});
}
grid = new SlickGrid(container, data, columns, options);
grid = new Slick.Grid(container, data, columns, options);
grid.invalidate();
});
@@ -89,5 +89,3 @@ define([
});
});
});
});

View File

@@ -1,25 +1,32 @@
define(
["jquery",
"underscore",
"slickgrid/slick.grid",
"sources/selection/active_cell_capture",
"sources/selection/row_selector",
'sources/selection/xcell_selection_model',
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
"slickgrid",
'sources/slickgrid/pgslick.cellrangedecorator',
'sources/slickgrid/pgslick.cellrangeselector',
],
function ($, _, SlickGrid, ActiveCellCapture, RowSelector, XCellSelectionModel, Slick) {
import $ from 'jquery';
import _ from 'underscore';
import Slick from 'slickgrid';
import 'slickgrid.grid';
import RowSelector from 'sources/selection/row_selector';
import ActiveCellCapture from 'sources/selection/active_cell_capture';
import XCellSelectionModel from 'sources/selection/xcell_selection_model';
describe('RowSelector', function () {
var KEY_RIGHT = 39;
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_DOWN = 40;
describe("RowSelector", function () {
var container, data, columnDefinitions, grid, cellSelectionModel;
var SlickGrid = Slick.Grid;
beforeEach(function () {
container = $("<div></div>");
container = $('<div></div>');
container.height(9999);
container.width(9999);
@@ -50,14 +57,14 @@ define(
grid.registerPlugin(rowSelector);
grid.invalidate();
$("body").append(container);
$('body').append(container);
});
afterEach(function () {
$("body").find(container).remove();
$('body').find(container).remove();
});
it("renders an additional column on the left", function () {
it('renders an additional column on the left', function () {
expect(columnDefinitions.length).toBe(3);
var leftmostColumn = columnDefinitions[0];
@@ -66,26 +73,26 @@ define(
expect(leftmostColumn.selectable).toBe(false);
});
it("renders a span on the leftmost column", function () {
it('renders a span on the leftmost column', function () {
expect(container.find('.slick-row').length).toBe(10);
expect(container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]').length).toBe(10);
});
it("preserves the other attributes of column definitions", function () {
it('preserves the other attributes of column definitions', function () {
expect(columnDefinitions[1].id).toBe('1');
expect(columnDefinitions[1].selectable).toBe(true);
});
describe("selecting rows", function () {
describe("when the user clicks a row header span", function () {
it("selects the row", function () {
describe('selecting rows', function () {
describe('when the user clicks a row header span', function () {
it('selects the row', function () {
container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[0].click();
var selectedRanges = cellSelectionModel.getSelectedRanges();
expectOnlyTheFirstRowToBeSelected(selectedRanges);
});
it("add selected class to parent of the span", function () {
it('add selected class to parent of the span', function () {
container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[5].click();
expect($(container.find('.slick-row .slick-cell:first-child ')[5])
@@ -93,12 +100,12 @@ define(
});
});
describe("when the user clicks a row header", function () {
describe('when the user clicks a row header', function () {
beforeEach(function () {
container.find('.slick-row .slick-cell:first-child')[1].click();
});
it("selects the row", function () {
it('selects the row', function () {
var selectedRanges = cellSelectionModel.getSelectedRanges();
var row = selectedRanges[0];
@@ -110,14 +117,14 @@ define(
expect(row.toRow).toBe(1);
});
it("add selected class to parent of the span", function () {
it('add selected class to parent of the span', function () {
expect($(container.find('.slick-row .slick-cell:first-child ')[1])
.hasClass('selected')).toBeTruthy();
});
describe("when the user clicks again the same row header", function () {
it("add selected class to parent of the span", function () {
describe('when the user clicks again the same row header', function () {
it('add selected class to parent of the span', function () {
container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[1].click();
expect($(container.find('.slick-row .slick-cell:first-child ')[1])
@@ -125,16 +132,16 @@ define(
});
});
describe("and presses shift + down-arrow", function () {
describe('and presses shift + down-arrow', function () {
beforeEach(function () {
pressShiftArrow(KEY_DOWN);
});
it("keeps the last row selected", function () {
it('keeps the last row selected', function () {
expect(cellSelectionModel.getSelectedRanges().length).toBe(1);
});
it("grows the selection down", function () {
it('grows the selection down', function () {
var selectedRanges = cellSelectionModel.getSelectedRanges();
var row = selectedRanges[0];
@@ -146,7 +153,7 @@ define(
expect(row.toRow).toBe(2);
});
it("keeps selected class on rows 1 and 2", function () {
it('keeps selected class on rows 1 and 2', function () {
expect($(container.find('.slick-row .slick-cell:first-child ')[0])
.hasClass('selected')).toBeFalsy();
expect($(container.find('.slick-row .slick-cell:first-child ')[1])
@@ -233,8 +240,8 @@ define(
});
});
describe("when the user clicks multiple row headers", function () {
it("selects another row", function () {
describe('when the user clicks multiple row headers', function () {
it('selects another row', function () {
container.find('.slick-row .slick-cell:first-child')[4].click();
container.find('.slick-row .slick-cell:first-child')[0].click();
@@ -251,13 +258,13 @@ define(
});
});
describe("when a column was already selected", function () {
describe('when a column was already selected', function () {
beforeEach(function () {
var selectedRanges = [new Slick.Range(0, 0, 0, 1)];
cellSelectionModel.setSelectedRanges(selectedRanges);
});
it("deselects the column", function () {
it('deselects the column', function () {
container.find('.slick-row .slick-cell:first-child')[0].click();
var selectedRanges = cellSelectionModel.getSelectedRanges();
@@ -265,12 +272,12 @@ define(
});
});
describe("when the row is deselected through setSelectedRanges", function () {
describe('when the row is deselected through setSelectedRanges', function () {
beforeEach(function () {
container.find('.slick-row .slick-cell:first-child')[4].click();
});
it("should remove the selected class", function () {
it('should remove the selected class', function () {
cellSelectionModel.setSelectedRanges([]);
expect($(container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[4])
@@ -278,18 +285,18 @@ define(
});
});
describe("click a second time", function () {
describe('click a second time', function () {
beforeEach(function () {
container.find('.slick-row .slick-cell:first-child')[1].click();
});
it("removes the selected class", function () {
it('removes the selected class', function () {
container.find('.slick-row .slick-cell:first-child')[1].click();
expect($(container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[1])
.hasClass('selected')).toBeFalsy();
});
it("unselects the row", function () {
it('unselects the row', function () {
container.find('.slick-row .slick-cell:first-child')[1].click();
var selectedRanges = cellSelectionModel.getSelectedRanges();
@@ -299,7 +306,7 @@ define(
});
function pressShiftArrow(keyCode) {
var pressEvent = new $.Event("keydown");
var pressEvent = new $.Event('keydown');
pressEvent.shiftKey = true;
pressEvent.ctrlKey = false;
pressEvent.altKey = false;
@@ -307,7 +314,6 @@ define(
$(container.find('.grid-canvas')).trigger(pressEvent);
}
});
function expectOnlyTheFirstRowToBeSelected(selectedRanges) {
var row = selectedRanges[0];

View File

@@ -7,11 +7,10 @@
//
//////////////////////////////////////////////////////////////////////////
define([
'sources/selection/xcell_selection_model',
"slickgrid/slick.grid",
'slickgrid',
], function (XCellSelectionModel, SlickGrid, Slick) {
import XCellSelectionModel from 'sources/selection/xcell_selection_model';
import 'slickgrid.grid';
import Slick from 'slickgrid';
describe('XCellSelectionModel', function () {
var KEY_RIGHT = 39;
var KEY_LEFT = 37;
@@ -19,6 +18,7 @@ define([
var KEY_DOWN = 40;
var container, grid;
var SlickGrid = Slick.Grid;
var oldWindowParent = window.parent;
beforeEach(function () {
@@ -509,5 +509,3 @@ define([
expect(range.toCell).toBe(toCell);
}
});
})
;

View File

@@ -7,13 +7,12 @@
//
//////////////////////////////////////////////////////////////
define(["jquery",
"slickgrid/slick.grid",
"sources/selection/xcell_selection_model",
"sources/slickgrid/cell_selector",
"sources/selection/range_selection_helper"
],
function ($, SlickGrid, XCellSelectionModel, CellSelector, RangeSelectionHelper) {
import $ from "jquery";
import SlickGrid from "slickgrid.grid";
import XCellSelectionModel from "sources/selection/xcell_selection_model";
import CellSelector from "sources/slickgrid/cell_selector";
import RangeSelectionHelper from "sources/selection/range_selection_helper";
describe("CellSelector", function () {
var container, columns, cellSelector, data, cellSelectionModel, grid;
beforeEach(function () {
@@ -32,7 +31,7 @@ define(["jquery",
for (var i = 0; i < 10; i++) {
data.push({'some-column-name': 'some-value-' + i, 'second column': 'second value ' + i});
}
grid = new SlickGrid(container, data, columns);
grid = new Slick.Grid(container, data, columns);
cellSelectionModel = new XCellSelectionModel();
grid.setSelectionModel(cellSelectionModel);
@@ -74,4 +73,3 @@ define(["jquery",
});
});
});
});

View File

@@ -7,18 +7,19 @@
//
//////////////////////////////////////////////////////////////
define([
'sources/slickgrid/event_handlers/handle_query_output_keyboard_event',
'sources/selection/clipboard',
'sources/selection/range_selection_helper',
'sources/selection/xcell_selection_model',
'slickgrid'
],
function (handleQueryOutputKeyboardEvent, clipboard, RangeSelectionHelper, XCellSelectionModel) {
var Slick = window.Slick;
import HandleQueryOutputKeyboardEvent from 'sources/slickgrid/event_handlers/handle_query_output_keyboard_event';
import clipboard from 'sources/selection/clipboard';
import RangeSelectionHelper from 'sources/selection/range_selection_helper';
import XCellSelectionModel from 'sources/selection/xcell_selection_model';
import Slick from 'slickgrid';
import 'slickgrid.grid';
describe('#handleQueryOutputKeyboardEvent', function () {
var event, view, grid, slickEvent;
var SlickGrid = Slick.Grid;
var handleQueryOutputKeyboardEvent;
beforeEach(function () {
event = {
shiftKey: false,
@@ -36,7 +37,7 @@ function (handleQueryOutputKeyboardEvent, clipboard, RangeSelectionHelper, XCell
pos: 2,
name: 'secondColumn'
}];
grid = new Slick.Grid($('<div></div>'), data, columnDefinitions);
grid = new SlickGrid($('<div></div>'), data, columnDefinitions);
grid.setSelectionModel(new XCellSelectionModel());
slickEvent = {
@@ -45,6 +46,8 @@ function (handleQueryOutputKeyboardEvent, clipboard, RangeSelectionHelper, XCell
view = {};
spyOn(clipboard, 'copyTextToClipboard');
handleQueryOutputKeyboardEvent = HandleQueryOutputKeyboardEvent.bind(window);
debugger
});
describe("when a range is selected", function () {
@@ -140,4 +143,3 @@ function (handleQueryOutputKeyboardEvent, clipboard, RangeSelectionHelper, XCell
});
});
});
});

View File

@@ -1,139 +0,0 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function (file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
// If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
// then do not normalize the paths
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
allTestFiles.push(normalizedTestModule)
}
});
var sourcesDir = '/base/pgadmin/static/';
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base',
paths: {
'pgadmin': sourcesDir + 'js/pgadmin',
'alertify': sourcesDir + 'vendor/alertifyjs/alertify',
'jquery': sourcesDir + 'vendor/jquery/jquery-1.11.2',
'jquery.ui': sourcesDir + 'vendor/jquery-ui/jquery-ui-1.11.3',
'jquery.event.drag': sourcesDir + 'vendor/jquery-ui/jquery.event.drag-2.2',
'underscore': sourcesDir + 'vendor/underscore/underscore',
'underscore.string': sourcesDir + 'vendor/underscore/underscore.string',
'slickgrid': sourcesDir + 'vendor/slickgrid/slick.core',
'slickgrid/slick.grid': sourcesDir + 'vendor/slickgrid/slick.grid',
'translations': '/base/regression/javascript/fake_translations',
'pgadmin.browser.endpoints': '/base/regression/javascript/fake_endpoints',
'sources': sourcesDir + 'js',
'browser': '/base/pgadmin/browser/static/js'
},
shim: {
'underscore': {
exports: '_'
},
"slickgrid": {
"deps": [
'jquery', "jquery.ui", "jquery.event.drag"
],
"exports": 'window.Slick'
},
"slickgrid/slick.grid": {
"deps": [
'jquery', "jquery.ui", "jquery.event.drag", "slickgrid"
],
"exports": 'window.Slick.Grid'
},
"sources/slickgrid/pgslick.cellrangedecorator": {
"deps": [
"jquery"
],
"exports": 'PGRowRangeDecorator'
},
"sources/slickgrid/pgslick.cellrangeselector": {
"deps": [
"jquery", "sources/slickgrid/pgslick.cellrangedecorator"
],
"exports": 'PGCellRangeSelector'
},
"sources/selection/xcell_selection_model": {
"deps": [
"jquery", "sources/slickgrid/pgslick.cellrangeselector"
],
"exports": 'XCellSelectionModel'
},
"backbone": {
"deps": ['underscore', 'jquery'],
"exports": 'Backbone'
},
"backbone.paginator": {
"deps": ['underscore', 'jquery', 'backbone']
},
"bootstrap": {
"deps": ['jquery'],
},
"backgrid": {
"deps": ['backform'],
"exports": 'Backgrid',
},
"backgrid.select.all": {
"deps": ['backgrid']
},
"backgrid.paginator": {
"deps": ['backgrid', 'backbone.paginator']
},
"backgrid.filter": {
"deps": ['backgrid']
},
"backgrid.sizeable.columns": {
"deps": ['backgrid']
},
"bootstrap.switch": {
"deps": ['jquery', 'bootstrap'],
"exports": 'jQuery.fn.bootstrapSwitch'
},
"select2": {
"deps": ['jquery'],
"exports": 'jQuery.fn.select2'
},
"bootstrap.datepicker": {
"deps": ['jquery', 'bootstrap'],
"exports": 'jQuery.fn.datepicker'
},
"bootstrap.datetimepicker": {
"deps": ['jquery', 'bootstrap', 'moment'],
"exports": 'jQuery.fn.datetimepicker'
},
"pgadmin.backgrid": {
"deps": ["backgrid", "bootstrap.datetimepicker", "bootstrap.switch"],
},
"pgadmin.backform": {
"deps": ['backform', "pgadmin.backgrid", "select2"],
},
"jquery.event.drag": {
"deps": ['jquery'], "exports": 'jQuery.fn.drag'
},
"jquery.ui": {"deps": ['jquery']}
},
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});

View File

@@ -4,6 +4,7 @@ testscenarios==0.5.0
testtools==2.0.0
traceback2==1.4.0
unittest2==1.1.0
mock~=2.0.0
# Leave this at the end because there is a bug where the '--install-option' is applied to all subsequent requirements
chromedriver_installer==0.0.6 --install-option='--chromedriver-version=2.29'

29
web/webpack.config.js Normal file
View File

@@ -0,0 +1,29 @@
/* eslint-env node */
module.exports = {
context: __dirname + '/pgadmin/static/jsx',
entry: './components.jsx',
output: {
libraryTarget: 'amd',
path: __dirname + '/pgadmin/static/js/generated',
filename: 'reactComponents.js',
},
module: {
rules: [{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015', 'react'],
},
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
};

View File

@@ -0,0 +1,71 @@
/* eslint-env node */
const path = require('path');
const webpack = require('webpack');
const sourcesDir = path.resolve(__dirname, 'pgadmin/static');
const regressionDir = path.resolve(__dirname, 'regression');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
_: 'underscore',
'underscore.string': 'underscore.string',
}),
],
module: {
rules: [
{
test: /\.jsx?$/,
exclude: [/node_modules/, /vendor/],
use: {
loader: 'babel-loader',
options: {
presets: ['es2015'],
},
},
},
{
test: /.*slickgrid\/slick\.(?!core)*/,
loader: 'imports-loader?' +
'jquery.ui' +
',jquery.event.drag' +
',slickgrid',
}, {
test: /.*slickgrid\/plugins\/slick\.rowselectionmodel/,
loader: 'imports-loader?' +
'jquery.ui' +
',jquery.event.drag' +
',slickgrid' +
'!exports-loader?' +
'Slick.RowSelectionModel',
}, {
test: /.*slickgrid\/slick\.core.*/,
loader: 'imports-loader?' +
'jquery.ui' +
',jquery.event.drag' +
'!exports-loader?' +
'Slick',
}],
},
resolve: {
alias: {
'alertify': sourcesDir + '/vendor/alertifyjs/alertify',
'jquery': sourcesDir + '/vendor/jquery/jquery-1.11.2',
'jquery.ui': sourcesDir + '/vendor/jquery-ui/jquery-ui-1.11.3',
'jquery.event.drag': sourcesDir + '/vendor/jquery-ui/jquery.event.drag-2.2',
'sources': sourcesDir + '/js',
'underscore.string': sourcesDir + '/vendor/underscore/underscore.string',
'translations': regressionDir + '/javascript/fake_translations',
'pgadmin.browser.endpoints': regressionDir + '/javascript/fake_endpoints',
'slickgrid': sourcesDir + '/vendor/slickgrid/slick.core',
'slickgrid.grid': sourcesDir + '/vendor/slickgrid/slick.grid',
'slickgrid.rowselectionmodel': sourcesDir + '/vendor/slickgrid/plugins/slick.rowselectionmodel',
'browser': path.resolve(__dirname, 'pgadmin/browser/static/js'),
'pgadmin': sourcesDir + '/js/pgadmin',
},
},
};

File diff suppressed because it is too large Load Diff