<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License 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.
//
////////////////////////////////////////////////////////////////////////////

/* eslint-env es6, node */

'use strict';

const Realm = require('realm');
const TestCase = require('./asserts');

const isNodeProccess = (typeof process === 'object' && process + '' === '[object process]');
console.log("isnode " + isNodeProccess + " typeof " + typeof process === 'object');
function node_require(module) {
    return require(module);
}

let tmp;
let fs;
let execFile;

if (isNodeProccess) {
    tmp = node_require('tmp');
    fs = node_require('fs');
    execFile = node_require('child_process').execFile;
    tmp.setGracefulCleanup();
}

function uuid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function promisifiedRegister(server, username, password) {
    return new Promise((resolve, reject) => {
        Realm.Sync.User.register(server, username, password, (error, user) => {
            if (error) {
                console.log(`promisifiedRegister ${error}`);
                reject(error);
            } else {
                resolve(user);
            }
        });
    });
}

function promisifiedLogin(server, username, password) {
    return new Promise((resolve, reject) => {
        Realm.Sync.User.login(server, username, password, (error, user) => {
            if (error) {
                console.log(`promisifiedLogin ${error}`);
                reject(error);
            } else {
                resolve(user);
            }
        });
    });
}

function runOutOfProcess(nodeJsFilePath) {
    var nodeArgs = Array.prototype.slice.call(arguments);
    let tmpDir = tmp.dirSync();
    let content = fs.readFileSync(nodeJsFilePath, 'utf8');
    let tmpFile = tmp.fileSync({ dir: tmpDir.name });
    fs.appendFileSync(tmpFile.fd, content, { encoding: 'utf8' });
    nodeArgs[0] = tmpFile.name;
    return new Promise((resolve, reject) => {
        const child = execFile('node', nodeArgs, { cwd: tmpDir.name }, (error, stdout, stderr) => {
            if (error) {
                reject(new Error(`Error executing ${nodeJsFilePath} Error: ${error}`));
            }
            resolve();
        });
    })
}

module.exports = {

    testLocalRealmHasNoSession() {
        let realm = new Realm();
        TestCase.assertNull(realm.syncSession);
    },

    testProperties() {
        return promisifiedRegister('http://localhost:9080', uuid(), 'password').then(user => {
            return new Promise((resolve, reject) => {

                const accessTokenRefreshed = this;
                let successCounter = 0;
                function checkSuccess() {
                    successCounter++;
                    if (successCounter == 2) {
                        resolve();
                    }
                }

                function postTokenRefreshChecks(sender, error) {
                    try {
                        TestCase.assertEqual(error, accessTokenRefreshed);
                        TestCase.assertEqual(sender.url, `realm://localhost:9080/${user.identity}/myrealm`);
                        checkSuccess();
                    }
                    catch (e) {
                        reject(e)
                    }
                };

                // Let the error handler trigger our checks when the access token was refreshed.
                postTokenRefreshChecks._notifyOnAccessTokenRefreshed = accessTokenRefreshed;

                const config = { sync: { user, url: 'realm://localhost:9080/~/myrealm', error: postTokenRefreshChecks } };
                const realm = new Realm(config);
                const session = realm.syncSession;
                TestCase.assertInstanceOf(session, Realm.Sync.Session);
                TestCase.assertEqual(session.user.identity, user.identity);
                TestCase.assertEqual(session.config.url, config.sync.url);
                TestCase.assertEqual(session.config.user.identity, config.sync.user.identity);
                TestCase.assertUndefined(session.url);
                TestCase.assertEqual(session.state, 'active');
                checkSuccess();
            });
        });
    },

    testRealmOpen() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

        runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    const accessTokenRefreshed = this;
                    let successCounter = 0;

                    let config = {
                        sync: { user, url: `realm://localhost:9080/~/${realmName}` },
                        schema: [{ name: 'Dog', properties: { name: 'string' } }],
                    };

                    return Realm.open(config)
                        .then(realm => {
                            let actualObjectsCount = realm.objects('Dog').length;
                            TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Synced realm does not contain the expected objects count");
                            return realm.syncSession;
                        }).then(session => {
                            TestCase.assertInstanceOf(session, Realm.Sync.Session);
                            TestCase.assertEqual(session.user.identity, user.identity);
                            TestCase.assertEqual(session.config.url, config.sync.url);
                            TestCase.assertEqual(session.config.user.identity, config.sync.user.identity);
                            TestCase.assertEqual(session.state, 'active');
                        });
                });
            });
    },

    testRealmOpenAsync() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

        runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    return new Promise((resolve, reject) => {
                        const accessTokenRefreshed = this;
                        let successCounter = 0;

                        let config = {
                            sync: { user, url: `realm://localhost:9080/~/${realmName}` },
                            schema: [{ name: 'Dog', properties: { name: 'string' } }],
                        };

                        Realm.openAsync(config, (error, realm) => {
                            try {
                                if (error) {
                                    reject(error);
                                }

                                let actualObjectsCount = realm.objects('Dog').length;
                                TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Synced realm does not contain the expected objects count");

                                setTimeout(() => {
                                    try {
                                        const session = realm.syncSession;
                                        TestCase.assertInstanceOf(session, Realm.Sync.Session);
                                        TestCase.assertEqual(session.user.identity, user.identity);
                                        TestCase.assertEqual(session.config.url, config.sync.url);
                                        TestCase.assertEqual(session.config.user.identity, config.sync.user.identity);
                                        TestCase.assertEqual(session.state, 'active');
                                        resolve();
                                    } catch (e) {
                                        reject(e);
                                    }
                                }, 50);
                            }
                            catch (e) {
                                reject(e);
                            }
                        });
                    });
                });
            });
    },

    testProgressNotificationsForRealmOpen() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

        runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    const accessTokenRefreshed = this;
                    let successCounter = 0;
                    let progressNotificationCalled = false;
                    let config = {
                        sync: {
                            user,
                            url: `realm://localhost:9080/~/${realmName}`,
                            _onDownloadProgress: (transferred, remaining) => {
                                progressNotificationCalled = true
                            },
                        },
                        schema: [{ name: 'Dog', properties: { name: 'string' } }],
                    };

                    return Realm.open(config)
                        .then(realm => {
                        }).then(session => {
                            TestCase.assertTrue(progressNotificationCalled, "Progress notification not called for Realm.open");
                        });
                });
            });
    },

    testProgressNotificationsForRealmOpenAsync() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

        runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    return new Promise((resolve, reject) => {
                        let progressNotificationCalled = false;
                        let config = {
                            sync: { user, url: `realm://localhost:9080/~/${realmName}`,
                                _onDownloadProgress: (transferred, remaining) => {
                                    progressNotificationCalled = true
                                },
                            },
                            schema: [{ name: 'Dog', properties: { name: 'string' } }],
                        };

                        Realm.openAsync(config, (error, realm) => {
                            try {
                                if (error) {
                                    reject(error);
                                }

                                setTimeout(() => {
                                    try {
                                        TestCase.assertTrue(progressNotificationCalled, "Progress notification not called for Realm.openAsync");
                                        resolve();
                                    } catch (e) {
                                        reject(e);
                                    }
                                }, 50);
                            }
                            catch (e) {
                                reject(e);
                            }
                        });
                    });
                });
            });
    },

    testRealmOpenAsyncNoSchema() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

       runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    return new Promise((resolve, reject) => {
                        const accessTokenRefreshed = this;
                        let successCounter = 0;

                        let config = {
                            sync: { user, url: `realm://localhost:9080/~/${realmName}` }
                        };

                        Realm.openAsync(config, (error, realm) => {
                            try {
                                if (error) {
                                    reject(error);
                                }

                                let actualObjectsCount = realm.objects('Dog').length;
                                TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Synced realm does not contain the expected objects count");

                                let firstDog = realm.objects('Dog')[0];
                                TestCase.assertTrue(({}).hasOwnProperty.call(firstDog, 'name'), "Synced realm does not have an inffered schema");
                                TestCase.assertTrue(firstDog.name, "Synced realm object's property should have a value");
                                TestCase.assertTrue(firstDog.name.indexOf('Lassy') !== -1, "Synced realm object's property should contain the actual written value");

                                const session = realm.syncSession;
                                TestCase.assertInstanceOf(session, Realm.Sync.Session);
                                TestCase.assertEqual(session.user.identity, user.identity);
                                TestCase.assertEqual(session.config.url, config.sync.url);
                                TestCase.assertEqual(session.config.user.identity, config.sync.user.identity);
                                TestCase.assertEqual(session.state, 'active');
                                resolve();
                            }
                            catch (e) {
                                reject(e);
                            }
                        });
                    });
                });
            });
    },

    testRealmOpenLocalRealm() {
        const username = uuid();
        const expectedObjectsCount = 3;

        return new Promise((resolve, reject) => {
            const accessTokenRefreshed = this;
            let successCounter = 0;

            let config = {
                schema: [{ name: 'Dog', properties: { name: 'string' } }],
            };

            Realm.open(config).then(realm => {
                realm.write(() => {
                    for (let i = 1; i <= 3; i++) {
                        realm.create('Dog', { name: `Lassy ${i}` });
                    }
                });

                let actualObjectsCount = realm.objects('Dog').length;
                TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Local realm does not contain the expected objects count");
                resolve();
            }).catch(error => reject(error));
        });
    },

    testRealmOpenAsyncLocalRealm() {
        const username = uuid();
        const expectedObjectsCount = 3;

        return new Promise((resolve, reject) => {
            const accessTokenRefreshed = this;
            let successCounter = 0;

            let config = {
                schema: [{ name: 'Dog', properties: { name: 'string' } }],
            };

            Realm.openAsync(config, (error, realm) => {
                try {
                    if (error) {
                        reject(error);
                    }

                    realm.write(() => {
                        for (let i = 1; i <= 3; i++) {
                            realm.create('Dog', { name: `Lassy ${i}` });
                        }
                    });

                    let actualObjectsCount = realm.objects('Dog').length;
                    TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Local realm does not contain the expected objects count");
                    resolve();
                }
                catch (e) {
                    reject(e);
                }
            });
        });
    },

    testErrorHandling() {
        return promisifiedRegister('http://localhost:9080', uuid(), 'password').then(user => {
            return new Promise((resolve, _reject) => {
                const config = { sync: { user, url: 'realm://localhost:9080/~/myrealm' } };
                config.sync.error = (sender, error) => {
                    try {
                        TestCase.assertEqual(error.message, 'simulated error');
                        TestCase.assertEqual(error.code, 123);
                        resolve();
                    }
                    catch (e) {
                        _reject(e);
                    }
                };
                const realm = new Realm(config);
                const session = realm.syncSession;

                TestCase.assertEqual(session.config.error, config.sync.error);
                session._simulateError(123, 'simulated error');
            });
        });
    }
}<commit_msg>rename test variable to reflect parameter meaning<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License 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.
//
////////////////////////////////////////////////////////////////////////////

/* eslint-env es6, node */

'use strict';

const Realm = require('realm');
const TestCase = require('./asserts');

const isNodeProccess = (typeof process === 'object' && process + '' === '[object process]');
console.log("isnode " + isNodeProccess + " typeof " + typeof process === 'object');
function node_require(module) {
    return require(module);
}

let tmp;
let fs;
let execFile;

if (isNodeProccess) {
    tmp = node_require('tmp');
    fs = node_require('fs');
    execFile = node_require('child_process').execFile;
    tmp.setGracefulCleanup();
}

function uuid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function promisifiedRegister(server, username, password) {
    return new Promise((resolve, reject) => {
        Realm.Sync.User.register(server, username, password, (error, user) => {
            if (error) {
                console.log(`promisifiedRegister ${error}`);
                reject(error);
            } else {
                resolve(user);
            }
        });
    });
}

function promisifiedLogin(server, username, password) {
    return new Promise((resolve, reject) => {
        Realm.Sync.User.login(server, username, password, (error, user) => {
            if (error) {
                console.log(`promisifiedLogin ${error}`);
                reject(error);
            } else {
                resolve(user);
            }
        });
    });
}

function runOutOfProcess(nodeJsFilePath) {
    var nodeArgs = Array.prototype.slice.call(arguments);
    let tmpDir = tmp.dirSync();
    let content = fs.readFileSync(nodeJsFilePath, 'utf8');
    let tmpFile = tmp.fileSync({ dir: tmpDir.name });
    fs.appendFileSync(tmpFile.fd, content, { encoding: 'utf8' });
    nodeArgs[0] = tmpFile.name;
    return new Promise((resolve, reject) => {
        const child = execFile('node', nodeArgs, { cwd: tmpDir.name }, (error, stdout, stderr) => {
            if (error) {
                reject(new Error(`Error executing ${nodeJsFilePath} Error: ${error}`));
            }
            resolve();
        });
    })
}

module.exports = {

    testLocalRealmHasNoSession() {
        let realm = new Realm();
        TestCase.assertNull(realm.syncSession);
    },

    testProperties() {
        return promisifiedRegister('http://localhost:9080', uuid(), 'password').then(user => {
            return new Promise((resolve, reject) => {

                const accessTokenRefreshed = this;
                let successCounter = 0;
                function checkSuccess() {
                    successCounter++;
                    if (successCounter == 2) {
                        resolve();
                    }
                }

                function postTokenRefreshChecks(sender, error) {
                    try {
                        TestCase.assertEqual(error, accessTokenRefreshed);
                        TestCase.assertEqual(sender.url, `realm://localhost:9080/${user.identity}/myrealm`);
                        checkSuccess();
                    }
                    catch (e) {
                        reject(e)
                    }
                };

                // Let the error handler trigger our checks when the access token was refreshed.
                postTokenRefreshChecks._notifyOnAccessTokenRefreshed = accessTokenRefreshed;

                const config = { sync: { user, url: 'realm://localhost:9080/~/myrealm', error: postTokenRefreshChecks } };
                const realm = new Realm(config);
                const session = realm.syncSession;
                TestCase.assertInstanceOf(session, Realm.Sync.Session);
                TestCase.assertEqual(session.user.identity, user.identity);
                TestCase.assertEqual(session.config.url, config.sync.url);
                TestCase.assertEqual(session.config.user.identity, config.sync.user.identity);
                TestCase.assertUndefined(session.url);
                TestCase.assertEqual(session.state, 'active');
                checkSuccess();
            });
        });
    },

    testRealmOpen() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

        runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    const accessTokenRefreshed = this;
                    let successCounter = 0;

                    let config = {
                        sync: { user, url: `realm://localhost:9080/~/${realmName}` },
                        schema: [{ name: 'Dog', properties: { name: 'string' } }],
                    };

                    return Realm.open(config)
                        .then(realm => {
                            let actualObjectsCount = realm.objects('Dog').length;
                            TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Synced realm does not contain the expected objects count");
                            return realm.syncSession;
                        }).then(session => {
                            TestCase.assertInstanceOf(session, Realm.Sync.Session);
                            TestCase.assertEqual(session.user.identity, user.identity);
                            TestCase.assertEqual(session.config.url, config.sync.url);
                            TestCase.assertEqual(session.config.user.identity, config.sync.user.identity);
                            TestCase.assertEqual(session.state, 'active');
                        });
                });
            });
    },

    testRealmOpenAsync() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

        runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    return new Promise((resolve, reject) => {
                        const accessTokenRefreshed = this;
                        let successCounter = 0;

                        let config = {
                            sync: { user, url: `realm://localhost:9080/~/${realmName}` },
                            schema: [{ name: 'Dog', properties: { name: 'string' } }],
                        };

                        Realm.openAsync(config, (error, realm) => {
                            try {
                                if (error) {
                                    reject(error);
                                }

                                let actualObjectsCount = realm.objects('Dog').length;
                                TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Synced realm does not contain the expected objects count");

                                setTimeout(() => {
                                    try {
                                        const session = realm.syncSession;
                                        TestCase.assertInstanceOf(session, Realm.Sync.Session);
                                        TestCase.assertEqual(session.user.identity, user.identity);
                                        TestCase.assertEqual(session.config.url, config.sync.url);
                                        TestCase.assertEqual(session.config.user.identity, config.sync.user.identity);
                                        TestCase.assertEqual(session.state, 'active');
                                        resolve();
                                    } catch (e) {
                                        reject(e);
                                    }
                                }, 50);
                            }
                            catch (e) {
                                reject(e);
                            }
                        });
                    });
                });
            });
    },

    testProgressNotificationsForRealmOpen() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

        runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    const accessTokenRefreshed = this;
                    let successCounter = 0;
                    let progressNotificationCalled = false;
                    let config = {
                        sync: {
                            user,
                            url: `realm://localhost:9080/~/${realmName}`,
                            _onDownloadProgress: (transferred, total) => {
                                progressNotificationCalled = true
                            },
                        },
                        schema: [{ name: 'Dog', properties: { name: 'string' } }],
                    };

                    return Realm.open(config)
                        .then(realm => {
                        }).then(session => {
                            TestCase.assertTrue(progressNotificationCalled, "Progress notification not called for Realm.open");
                        });
                });
            });
    },

    testProgressNotificationsForRealmOpenAsync() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

        runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    return new Promise((resolve, reject) => {
                        let progressNotificationCalled = false;
                        let config = {
                            sync: { user, url: `realm://localhost:9080/~/${realmName}`,
                                _onDownloadProgress: (transferred, total) => {
                                    progressNotificationCalled = true
                                },
                            },
                            schema: [{ name: 'Dog', properties: { name: 'string' } }],
                        };

                        Realm.openAsync(config, (error, realm) => {
                            try {
                                if (error) {
                                    reject(error);
                                }

                                setTimeout(() => {
                                    try {
                                        TestCase.assertTrue(progressNotificationCalled, "Progress notification not called for Realm.openAsync");
                                        resolve();
                                    } catch (e) {
                                        reject(e);
                                    }
                                }, 50);
                            }
                            catch (e) {
                                reject(e);
                            }
                        });
                    });
                });
            });
    },

    testRealmOpenAsyncNoSchema() {
        if (!isNodeProccess) {
            return Promise.resolve();
        }

        const username = uuid();
        const realmName = uuid();
        const expectedObjectsCount = 3;

       runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
            .then(() => {
                return promisifiedLogin('http://localhost:9080', username, 'password').then(user => {
                    return new Promise((resolve, reject) => {
                        const accessTokenRefreshed = this;
                        let successCounter = 0;

                        let config = {
                            sync: { user, url: `realm://localhost:9080/~/${realmName}` }
                        };

                        Realm.openAsync(config, (error, realm) => {
                            try {
                                if (error) {
                                    reject(error);
                                }

                                let actualObjectsCount = realm.objects('Dog').length;
                                TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Synced realm does not contain the expected objects count");

                                let firstDog = realm.objects('Dog')[0];
                                TestCase.assertTrue(({}).hasOwnProperty.call(firstDog, 'name'), "Synced realm does not have an inffered schema");
                                TestCase.assertTrue(firstDog.name, "Synced realm object's property should have a value");
                                TestCase.assertTrue(firstDog.name.indexOf('Lassy') !== -1, "Synced realm object's property should contain the actual written value");

                                const session = realm.syncSession;
                                TestCase.assertInstanceOf(session, Realm.Sync.Session);
                                TestCase.assertEqual(session.user.identity, user.identity);
                                TestCase.assertEqual(session.config.url, config.sync.url);
                                TestCase.assertEqual(session.config.user.identity, config.sync.user.identity);
                                TestCase.assertEqual(session.state, 'active');
                                resolve();
                            }
                            catch (e) {
                                reject(e);
                            }
                        });
                    });
                });
            });
    },

    testRealmOpenLocalRealm() {
        const username = uuid();
        const expectedObjectsCount = 3;

        return new Promise((resolve, reject) => {
            const accessTokenRefreshed = this;
            let successCounter = 0;

            let config = {
                schema: [{ name: 'Dog', properties: { name: 'string' } }],
            };

            Realm.open(config).then(realm => {
                realm.write(() => {
                    for (let i = 1; i <= 3; i++) {
                        realm.create('Dog', { name: `Lassy ${i}` });
                    }
                });

                let actualObjectsCount = realm.objects('Dog').length;
                TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Local realm does not contain the expected objects count");
                resolve();
            }).catch(error => reject(error));
        });
    },

    testRealmOpenAsyncLocalRealm() {
        const username = uuid();
        const expectedObjectsCount = 3;

        return new Promise((resolve, reject) => {
            const accessTokenRefreshed = this;
            let successCounter = 0;

            let config = {
                schema: [{ name: 'Dog', properties: { name: 'string' } }],
            };

            Realm.openAsync(config, (error, realm) => {
                try {
                    if (error) {
                        reject(error);
                    }

                    realm.write(() => {
                        for (let i = 1; i <= 3; i++) {
                            realm.create('Dog', { name: `Lassy ${i}` });
                        }
                    });

                    let actualObjectsCount = realm.objects('Dog').length;
                    TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Local realm does not contain the expected objects count");
                    resolve();
                }
                catch (e) {
                    reject(e);
                }
            });
        });
    },

    testErrorHandling() {
        return promisifiedRegister('http://localhost:9080', uuid(), 'password').then(user => {
            return new Promise((resolve, _reject) => {
                const config = { sync: { user, url: 'realm://localhost:9080/~/myrealm' } };
                config.sync.error = (sender, error) => {
                    try {
                        TestCase.assertEqual(error.message, 'simulated error');
                        TestCase.assertEqual(error.code, 123);
                        resolve();
                    }
                    catch (e) {
                        _reject(e);
                    }
                };
                const realm = new Realm(config);
                const session = realm.syncSession;

                TestCase.assertEqual(session.config.error, config.sync.error);
                session._simulateError(123, 'simulated error');
            });
        });
    }
}<|endoftext|>


<commit_before>
// this variable will store the visualisation so we can delete it when we need to
var visjsobj;

Template.raceData_visjs.onRendered(function () {
    // template rendered
    initBlobVis();
});

// template events
Template.raceData.events({
    "click #driver-dob": function () {
        initDriverDob();
    },
    "click #driver-speed": function () {
        initBlobVis();
    },
    "click #driver-fastest-lap": function () {
        initDriverFastestLap();
    }
});

function initDriverFastestLap() {
    // TODO
    $.getJSON("20160501_RussianGrandPrixdata.json", function (json) {
        // console.log(data);
        var results = getRaceResults(json);
        var nodes = [];
        var edges = [];
        // console.log(results);

        // iterate over the drivers in the result set
        $.each(results, function (index, driver) {
            // print each driver name and speed
            var driverName = driver.Driver.driverId;
            var driverPosition = Number(driver.position);
            var fastestLap = driver.FastestLap;
            var fastestLapNumber = 0.0;
            if (fastestLap) {
                fastestLapNumber = Number(fastestLap.lap);
            }

            // push nodes
            if (fastestLapNumber > 0.0) {
                nodes.push({
                    id: index,
                    value: fastestLapNumber,
                    label: driverName + ":" + driverPosition,
                    title: "Lap#" + fastestLapNumber
                });
            }
        });

        //
        // build vis stuff
        //

        // clear out the old visualisation if needed
        if (visjsobj !== undefined) {
            visjsobj.destroy();
        }

        var container = document.getElementById("visjs");

        var data = {
            nodes: nodes,
            edges: edges
        }
        var options = {
            nodes: {
                shape: "dot"
            }
        }

        visjsobj = new vis.Network(container, data, options);

    });
}

function initDriverDob() {
    $.getJSON("20160501_RussianGrandPrixdata.json", function (json) {
        // console.log(data);
        var results = getRaceResults(json);
        var items = [];
        // console.log(results);

        // iterate over the drivers in the result set
        $.each(results, function (index, driver) {
            // print each driver name and speed
            var driverName = driver.Driver.driverId;
            var driverPosition = Number(driver.position);
            var driverDob = driver.Driver.dateOfBirth;

            // push items
            items.push({
                id: index,
                content: driverName + ":" + driverPosition,
                start: driverDob
            });

        });

        //
        // build vis stuff
        //

        // clear out the old visualisation if needed
        if (visjsobj !== undefined) {
            visjsobj.destroy();
        }

        var container = document.getElementById("visjs");

        var options = {};

        visjsobj = new vis.Timeline(container, items, options);

    });

}

// function that creates a new blobby visualisation
function initBlobVis() {
    // try to get json data
    $.getJSON("20160501_RussianGrandPrixdata.json", function (json) {
        // console.log(data);
        var results = getRaceResults(json);
        var nodes = [];
        var edges = [];
        // console.log(results);

        // iterate over the drivers in the result set
        $.each(results, function (index, driver) {
            // print each driver name and speed
            var driverName = driver.Driver.driverId;
            var driverPosition = Number(driver.position);
            var fastestLap = driver.FastestLap;
            var avgSpeed = 0.0;
            if (fastestLap) {
                avgSpeed = Number(fastestLap.AverageSpeed.speed);
            }

            // push nodes
            if (avgSpeed > 1.0) {
                nodes.push({
                    id: index,
                    value: avgSpeed,
                    label: driverName + ":" + driverPosition,
                    title: avgSpeed + "kph"
                });
            }
        });

        //
        // build vis stuff
        //

        // clear out the old visualisation if needed
        if (visjsobj !== undefined) {
            visjsobj.destroy();
        }

        var container = document.getElementById("visjs");

        var data = {
            nodes: nodes,
            edges: edges
        }
        var options = {
            nodes: {
                shape: "dot"
            }
        }

        visjsobj = new vis.Network(container, data, options);

    });

}

// returns the array of results from the race
function getRaceResults(json) {

    if (!json)
        return [];

    return json.MRData.RaceTable.Races[0].Results;
}
<commit_msg>remove unnecessary comments<commit_after>
// this variable will store the visualisation so we can delete it when we need to
var visjsobj;

Template.raceData_visjs.onRendered(function () {
    // template rendered
    initBlobVis();
});

// template events
Template.raceData.events({
    "click #driver-dob": function () {
        initDriverDob();
    },
    "click #driver-speed": function () {
        initBlobVis();
    },
    "click #driver-fastest-lap": function () {
        initDriverFastestLap();
    }
});

function initDriverFastestLap() {
    // TODO
    $.getJSON("20160501_RussianGrandPrixdata.json", function (json) {
        // console.log(data);
        var results = getRaceResults(json);
        var nodes = [];
        var edges = [];
        // console.log(results);

        // iterate over the drivers in the result set
        $.each(results, function (index, driver) {
            // print each driver name and speed
            var driverName = driver.Driver.driverId;
            var driverPosition = Number(driver.position);
            var fastestLap = driver.FastestLap;
            var fastestLapNumber = 0.0;
            if (fastestLap) {
                fastestLapNumber = Number(fastestLap.lap);
            }

            // push nodes
            if (fastestLapNumber > 0.0) {
                nodes.push({
                    id: index,
                    value: fastestLapNumber,
                    label: driverName + ":" + driverPosition,
                    title: "Lap#" + fastestLapNumber
                });
            }
        });

        //
        // build vis stuff
        //

        // clear out the old visualisation if needed
        if (visjsobj !== undefined) {
            visjsobj.destroy();
        }

        var container = document.getElementById("visjs");

        var data = {
            nodes: nodes,
            edges: edges
        }
        var options = {
            nodes: {
                shape: "dot"
            }
        }

        visjsobj = new vis.Network(container, data, options);

    });
}

function initDriverDob() {
    $.getJSON("20160501_RussianGrandPrixdata.json", function (json) {
        // console.log(data);
        var results = getRaceResults(json);
        var items = [];
        // console.log(results);

        // iterate over the drivers in the result set
        $.each(results, function (index, driver) {
            // print each driver name and speed
            var driverName = driver.Driver.driverId;
            var driverPosition = Number(driver.position);
            var driverDob = driver.Driver.dateOfBirth;

            // push items
            items.push({
                id: index,
                content: driverName + ":" + driverPosition,
                start: driverDob
            });

        });

        //
        // build vis stuff
        //

        // clear out the old visualisation if needed
        if (visjsobj !== undefined) {
            visjsobj.destroy();
        }

        var container = document.getElementById("visjs");

        var options = {};

        visjsobj = new vis.Timeline(container, items, options);

    });

}

// function that creates a new blobby visualisation
function initBlobVis() {
    // try to get json data
    $.getJSON("20160501_RussianGrandPrixdata.json", function (json) {
        var results = getRaceResults(json);
        var nodes = [];
        var edges = [];

        // iterate over the drivers in the result set
        $.each(results, function (index, driver) {
            var driverName = driver.Driver.driverId;
            var driverPosition = Number(driver.position);
            var fastestLap = driver.FastestLap;
            var avgSpeed = 0.0;
            if (fastestLap) {
                avgSpeed = Number(fastestLap.AverageSpeed.speed);
            }

            // push nodes
            if (avgSpeed > 1.0) {
                nodes.push({
                    id: index,
                    value: avgSpeed,
                    label: driverName + ":" + driverPosition,
                    title: avgSpeed + "kph"
                });
            }
        });

        //
        // build vis stuff
        //

        // clear out the old visualisation if needed
        if (visjsobj !== undefined) {
            visjsobj.destroy();
        }

        var container = document.getElementById("visjs");

        var data = {
            nodes: nodes,
            edges: edges
        }
        var options = {
            nodes: {
                shape: "dot"
            }
        }

        visjsobj = new vis.Network(container, data, options);

    });

}

// returns the array of results from the race
function getRaceResults(json) {

    if (!json)
        return [];

    return json.MRData.RaceTable.Races[0].Results;
}
<|endoftext|>


<commit_before>buster.testCase('Nested validation', {
  setUp: function() {
    this.valid = this.spy();
    this.invalid = this.spy();

    var Model = Backbone.Model.extend({
      validation: {
        'address.street': {
          required: true
        }
      }
    });

    this.model = new Model();
    this.view = new Backbone.View({model: this.model});

    Backbone.Validation.bind(this.view, {
      invalid: this.invalid,
      valid: this.valid
    });
  },

  "invalid": {
    setUp: function () {
      this.result = this.model.set({
        address: {
          street:''
        }
      });
    },

    "refutes setting invalid values": function() {
      refute(this.result);
    },

    "calls the invalid callback": function() {
      assert.calledWith(this.invalid, this.view, 'address.street', 'Address. street is required');
    },

    "is valid returns false for the specified attribute name": function () {
      refute(this.model.isValid('address.street'));
    },

    "is valid returns false for the specified attribute names": function () {
      refute(this.model.isValid(['address.street', 'address.street']));
    },

    "pre validate returns error message for the specified attribute name": function () {
      assert(this.model.preValidate('address.street', ''));
    }
  },

  "valid": {
    setUp: function () {
      this.result = this.model.set({
        address: {
          street: 'name'
        }
      });
    },

    "sets the value": function() {
      assert(this.result);
    },

    "calls the valid callback": function() {
      assert.calledWith(this.valid, this.view, 'address.street');
    },

    "is valid returns true for the specified attribute name": function () {
      assert(this.model.isValid('address.street'));
    },

    "is valid returns true for the specified attribute names": function () {
      assert(this.model.isValid(['address.street', 'address.street']));
    },

    "pre validate returns no error message for the specified attribute name": function () {
      refute(this.model.preValidate('address.street', 'street'));
    }
  }
});
<commit_msg>Added more tests for nested validation<commit_after>buster.testCase('Nested validation', {
  "one level": {
    setUp: function() {
      this.valid = this.spy();
      this.invalid = this.spy();

      var Model = Backbone.Model.extend({
        validation: {
          'address.street': {
            required: true,
            msg: 'error'
          }
        }
      });

      this.model = new Model();
      this.view = new Backbone.View({model: this.model});

      Backbone.Validation.bind(this.view, {
        invalid: this.invalid,
        valid: this.valid
      });
    },

    "invalid": {
      setUp: function () {
        this.result = this.model.set({
          address: {
            street:''
          }
        });
      },

      "refutes setting invalid values": function() {
        refute(this.result);
      },

      "calls the invalid callback": function() {
        assert.calledWith(this.invalid, this.view, 'address.street', 'error');
      },

      "is valid returns false for the specified attribute name": function () {
        refute(this.model.isValid('address.street'));
      },

      "is valid returns false for the specified attribute names": function () {
        refute(this.model.isValid(['address.street', 'address.street']));
      },

      "pre validate returns error message for the specified attribute name": function () {
        assert(this.model.preValidate('address.street', ''));
      }
    },

    "valid": {
      setUp: function () {
        this.result = this.model.set({
          address: {
            street: 'name'
          }
        });
      },

      "sets the value": function() {
        assert(this.result);
      },

      "calls the valid callback": function() {
        assert.calledWith(this.valid, this.view, 'address.street');
      },

      "is valid returns true for the specified attribute name": function () {
        assert(this.model.isValid('address.street'));
      },

      "is valid returns true for the specified attribute names": function () {
        assert(this.model.isValid(['address.street', 'address.street']));
      },

      "pre validate returns no error message for the specified attribute name": function () {
        refute(this.model.preValidate('address.street', 'street'));
      }
    }
  },

  "two levels": {
    setUp: function() {
      this.valid = this.spy();
      this.invalid = this.spy();

      var Model = Backbone.Model.extend({
        validation: {
          'foo.bar.baz': {
            required: true,
            msg: 'error'
          }
        }
      });

      this.model = new Model();
      this.view = new Backbone.View({model: this.model});

      Backbone.Validation.bind(this.view, {
        invalid: this.invalid,
        valid: this.valid
      });
    },

    "invalid": {
      setUp: function () {
        this.result = this.model.set({
          foo: {
            bar: {
              baz: ''
            }
          }
        });
      },

      "refutes setting invalid values": function() {
        refute(this.result);
      },

      "calls the invalid callback": function() {
        assert.calledWith(this.invalid, this.view, 'foo.bar.baz', 'error');
      },

      "is valid returns false for the specified attribute name": function () {
        refute(this.model.isValid('foo.bar.baz'));
      },

      "is valid returns false for the specified attribute names": function () {
        refute(this.model.isValid(['foo.bar.baz', 'foo.bar.baz']));
      },

      "pre validate returns error message for the specified attribute name": function () {
        assert(this.model.preValidate('foo.bar.baz', ''));
      }
    },

    "valid": {
      setUp: function () {
        this.result = this.model.set({
          foo: {
            bar: {
              baz: 'val'
            }
          }
        });
      },

      "sets the value": function() {
        assert(this.result);
      },

      "calls the valid callback": function() {
        assert.calledWith(this.valid, this.view, 'foo.bar.baz');
      },

      "is valid returns true for the specified attribute name": function () {
        assert(this.model.isValid('foo.bar.baz'));
      },

      "is valid returns true for the specified attribute names": function () {
        assert(this.model.isValid(['foo.bar.baz', 'foo.bar.baz']));
      },

      "pre validate returns no error message for the specified attribute name": function () {
        refute(this.model.preValidate('foo.bar.baz', 'val'));
      }
    }
  },

  "complex nesting": {
    setUp: function() {
      this.valid = this.spy();
      this.invalid = this.spy();

      var Model = Backbone.Model.extend({
        validation: {
          'foo.bar.baz': {
            required: true,
            msg: 'error'
          },
          'foo.foo': {
            required: true,
            msg: 'error'
          }
        }
      });

      this.model = new Model();
      this.view = new Backbone.View({model: this.model});

      Backbone.Validation.bind(this.view, {
        invalid: this.invalid,
        valid: this.valid
      });
    },

    "invalid": {
      setUp: function () {
        this.result = this.model.set({
          foo: {
            foo: '',
            bar: {
              baz: ''
            }
          }
        });
      },

      "refutes setting invalid values": function() {
        refute(this.result);
      },

      "calls the invalid callback": function() {
        assert.calledWith(this.invalid, this.view, 'foo.bar.baz', 'error');
        assert.calledWith(this.invalid, this.view, 'foo.foo', 'error');
      },

      "is valid returns false for the specified attribute name": function () {
        refute(this.model.isValid('foo.bar.baz'));
        refute(this.model.isValid('foo.foo'));
      },

      "is valid returns false for the specified attribute names": function () {
        refute(this.model.isValid(['foo.foo', 'foo.bar.baz']));
      },

      "pre validate returns error message for the specified attribute name": function () {
        assert(this.model.preValidate('foo.bar.baz', ''));
        assert(this.model.preValidate('foo.foo', ''));
      }
    },

    "valid": {
      setUp: function () {
        this.result = this.model.set({
          foo: {
            foo: 'val',
            bar: {
              baz: 'val'
            }
          }
        });
      },

      "sets the value": function() {
        assert(this.result);
      },

      "calls the valid callback": function() {
        assert.calledWith(this.valid, this.view, 'foo.bar.baz');
        assert.calledWith(this.valid, this.view, 'foo.foo');
      },

      "is valid returns true for the specified attribute name": function () {
        assert(this.model.isValid('foo.bar.baz'));
        assert(this.model.isValid('foo.foo'));
      },

      "is valid returns true for the specified attribute names": function () {
        assert(this.model.isValid(['foo.bar.baz', 'foo.foo']));
      },

      "pre validate returns no error message for the specified attribute name": function () {
        refute(this.model.preValidate('foo.bar.baz', 'val'));
        refute(this.model.preValidate('foo.foo', 'val'));
      }
    }
  }
});
<|endoftext|>


<commit_before>[
  {
    "name": "Example Presets",
    "presets": [
      {
        "id": "ekn39s",
        "type": "ENC",
        "name": "Online H.264",
        "cmd": ["ffmpeg", "-i", "{{infile}}", "-threads", "{{threads}}", "-vcodec", "libx264", "-coder", "0", "-flags", "-loop", "-cmp", "+chroma", "-partitions", "-parti8x8-parti4x4-partp8x8-partb8x8", "-me_method", "dia", "-subq", "0", "-me_range", "16", "-g", "250", "-keyint_min", "25", "-sc_threshold", "0", "-i_qfactor", "0.71", "-b_strategy", "0", "-qcomp", "0.6", "-qmin", "10", "-qmax", "51", "-qdiff", "4", "-bf", "0", "-refs", "1", "-directpred", "1", "-trellis", "0", "-flags2", "-bpyramid-mixed_refs-wpred-dct8x8+fastpskip-mbtree", "-wpredp", "0", "-acodec", "aac", "-ac", "2", "-b:a", "256k", "-r:a", "48k", "-strict", "experimental", "-vf", "yadif,scale=1024:576", "{{outfile}}-online.mov"]
      },
      {
        "id": "3KuI82",
        "type": "ENC",
        "name": "Screener",
        "cmd": ["ffmbc", "-i", "{{infile}}", "-threads", "{{threads}}", "-vcodec", "libx264", "-coder", "0", "-flags", "-loop", "-cmp", "+chroma", "-partitions", "-parti8x8-parti4x4-partp8x8-partb8x8", "-me_method", "dia", "-subq", "0", "-me_range", "16", "-g", "250", "-keyint_min", "25", "-sc_threshold", "0", "-i_qfactor", "0.71", "-b_strategy", "0", "-qcomp", "0.6", "-qmin", "10", "-qmax", "51", "-qdiff", "4", "-bf", "0", "-refs", "1", "-trellis", "0", "-wpredp", "0", "-acodec", "libfaac", "-ac", "2", "-ab", "128k", "-ar", "48k", "-strict", "experimental", "-vf", "yadif,scale=640:360", "{{outfile}}-screener.mov"]
      },
      {
        "id": "k8Ea25",
        "type": "ENC",
        "name": "Webpost HD",
        "cmd": [
          ["ffmpeg", "-i", "{{infile}}", "-crf", "26", "-flags", "+loop+mv4", "-cmp", "256", "-partitions", "+parti4x4+parti8x8+partp4x4+partp8x8+partb8x8", "-me_method", "hex", "-subq", "7", "-trellis", "1", "-refs", "5", "-bf", "0", "-flags2", "+mixed_refs", "-coder", "0", "-me_range", "16", "-g", "250", "-keyint_min", "25", "-sc_threshold", "40", "-i_qfactor", "0.71", "-qmin", "10", "-qmax", "51", "-acodec", "aac", "-b:a", "192k", "-ac", "2", "-r:a", "48k", "-strict", "experimental", "-vf", "yadif,scale=960:540", "-threads", "{{threads}}", "{{outfile}}.mp4"],
          ["qtfaststart.py", "{{outfile}}.mp4"]
        ]
      }
    ]
  }
]
<commit_msg>replaced ffmpeg with ffmbc only, including "-faststart auto"<commit_after>[
  {
    "name": "Example Presets",
    "presets": [
      {
        "id": "ekn39s",
        "type": "ENC",
        "name": "Online H.264",
        "cmd": ["ffmbc", "-i", "{{infile}}", "-threads", "{{threads}}", "-vcodec", "libx264", "-coder", "0", "-flags", "-loop", "-cmp", "+chroma", "-partitions", "-parti8x8-parti4x4-partp8x8-partb8x8", "-me_method", "dia", "-subq", "0", "-me_range", "16", "-g", "250", "-keyint_min", "25", "-sc_threshold", "0", "-i_qfactor", "0.71", "-b_strategy", "0", "-qcomp", "0.6", "-qmin", "10", "-qmax", "51", "-qdiff", "4", "-bf", "0", "-refs", "1", "-directpred", "1", "-trellis", "0", "-flags2", "-bpyramid-mixed_refs-wpred-dct8x8+fastpskip-mbtree", "-wpredp", "0", "-acodec", "libfaac", "-ac", "2", "-b:a", "256k", "-r:a", "48k", "-strict", "experimental", "-vf", "yadif,scale=1024:576", "-faststart", "auto", "{{outfile}}-online.mov"]
      },
      {
        "id": "3KuI82",
        "type": "ENC",
        "name": "Screener",
        "cmd": ["ffmbc", "-i", "{{infile}}", "-threads", "{{threads}}", "-vcodec", "libx264", "-coder", "0", "-flags", "-loop", "-cmp", "+chroma", "-partitions", "-parti8x8-parti4x4-partp8x8-partb8x8", "-me_method", "dia", "-subq", "0", "-me_range", "16", "-g", "250", "-keyint_min", "25", "-sc_threshold", "0", "-i_qfactor", "0.71", "-b_strategy", "0", "-qcomp", "0.6", "-qmin", "10", "-qmax", "51", "-qdiff", "4", "-bf", "0", "-refs", "1", "-trellis", "0", "-wpredp", "0", "-acodec", "libfaac", "-ac", "2", "-ab", "128k", "-ar", "48k", "-strict", "experimental", "-vf", "yadif,scale=640:360", "-faststart", "auto", "{{outfile}}-screener.mov"]
      },
      {
        "id": "k8Ea25",
        "type": "ENC",
        "name": "Webpost HD",
        "cmd": [
          ["ffmbc", "-i", "{{infile}}", "-crf", "26", "-flags", "+loop+mv4", "-cmp", "256", "-partitions", "+parti4x4+parti8x8+partp4x4+partp8x8+partb8x8", "-me_method", "hex", "-subq", "7", "-trellis", "1", "-refs", "5", "-bf", "0", "-flags2", "+mixed_refs", "-coder", "0", "-me_range", "16", "-g", "250", "-keyint_min", "25", "-sc_threshold", "40", "-i_qfactor", "0.71", "-qmin", "10", "-qmax", "51", "-acodec", "libfaac", "-b:a", "192k", "-ac", "2", "-r:a", "48k", "-strict", "experimental", "-vf", "yadif,scale=960:540", "-threads", "{{threads}}", "-faststart", "auto", "{{outfile}}.mp4"]
        ]
      }
    ]
  }
]
<|endoftext|>


<commit_before>import { getOwner } from '@ember/application';
import { merge, assign as _assign } from '@ember/polyfills';
import { get } from '@ember/object';
import Ember from 'ember';
import defaultHammerEvents from './hammer-events';
import dasherizedToCamel from './utils/string/dasherized-to-camel';
import mobileDetection from './utils/is-mobile';

const {
  EventDispatcher,
} = Ember;

const eventEndings = {
  pan: ['Start', 'Move', 'End', 'Cancel', 'Left', 'Right', 'Up', 'Down'],
  pinch: ['Start', 'Move', 'End', 'Cancel', 'In', 'Out'],
  press: ['Up'],
  rotate: ['Start', 'Move', 'End', 'Cancel'],
  swipe: ['Left', 'Right', 'Up', 'Down'],
  tap: []
};

const assign = _assign || merge;

const notFocusableTypes = ['submit', 'file', 'button', 'hidden', 'reset', 'range', 'radio', 'image', 'checkbox'];

const fastFocusEvents = ['click', 'touchend'];

export default EventDispatcher.extend({

  /**
   Whether or not to cache handler paths on the element
   when `useCapture` is also true.
   This needs to be replaced by a feature flag.
   @private
   @type {boolean}
   */
  useFastPaths: false,
  useCapture: false,

  _gestures: null,
  _initializeGestures() {
    const list = getModuleList();
    const events = assign({}, defaultHammerEvents);

    list.forEach((name) => {
      const recognizer = getOwner(this).factoryFor('ember-gesture:recognizers/' + name);

      if (recognizer) {
        addEvent(events, recognizer.class.recognizer, recognizer.class.eventName || name);
      }
    });

    // add them to the event dispatcher
    this.set('_gestures', events);

  },

  _fastFocus() {
    let rootElementSelector = get(this, 'rootElement');
    let rootElement;
    if (rootElementSelector.nodeType) {
      rootElement = rootElementSelector;
    } else {
      rootElement = document.querySelector(rootElementSelector);
    }

    fastFocusEvents.forEach((event) => {
      let listener = this._gestureEvents[event] = (e) => {
        if (mobileDetection.is()) {
          let element = e.currentTarget;
          let target = e.target;

          /*
           If the click was on an input element that needs to be able to focus, recast
           the click as a "focus" event.
           This fixes tap events on mobile where keyboardShrinksView or similar is true.
           Such devices depend on the ghost click to trigger focus, but the ghost click
           will never reach the element.
           */

          //fastfocus
          if (element.tagName === 'TEXTAREA' || (element.tagName === 'INPUT' && notFocusableTypes.indexOf(element.getAttribute('type')) === -1)) {
            element.focus();

          } else if (target.tagName === 'TEXTAREA' || (target.tagName === 'INPUT' && notFocusableTypes.indexOf(target.getAttribute('type')) === -1)) {
            target.focus();
          }
        }
      };
      rootElement.addEventListener(event, listener);
    });
  },

  willDestroy() {
    let rootElementSelector = get(this, 'rootElement');
    let rootElement;
    if (rootElementSelector.nodeType) {
      rootElement = rootElementSelector;
    } else {
      rootElement = document.querySelector(rootElementSelector);
    }

    if (rootElement) {
      for (let event in this._gestureEvents) {
        rootElement.removeEventListener(event, this._gestureEvents[event]);
        delete this._gestureEvents[event];
      }
    }
    this._super(...arguments);
  },

  _finalEvents: null,

  init() {
    this._gestureEvents = Object.create(null);
    this._super(...arguments);
  },

  setup(addedEvents, rootElement) {
    this._initializeGestures();
    let events = assign({}, get(this, 'events'));

    // remove undesirable events from Ember's Eventing
    if (this.get('removeTracking')) {
      events.touchstart = null;
      events.touchmove = null;
      events.touchcancel = null;
      events.touchend = null;

      events.mousedown = null;
      events.mouseenter = null;
      events.mousemove = null;
      events.mouseleave = null;
      events.mouseup = null;

      events.drag = null;
      events.dragend = null;
      events.dragenter = null;
      events.dragleave = null;
      events.dragover = null;
      events.dragstart = null;
      events.drop = null;

      events.dblclick = null;
    }

    // delete unwanted events
    for (let event in events) {
      if (events.hasOwnProperty(event) && !events[event]) {
        delete events[event];
      }
    }

    // override default events
    this.set('events', events);

    // add our events to addition events
    let additionalEvents = assign({}, addedEvents);
    additionalEvents = assign(additionalEvents, this.get('_gestures'));

    this._fastFocus();

    return this._super(additionalEvents, rootElement);
  }

});

function addEvent(hash, gesture, name) {
  const eventName = dasherizedToCamel(name);
  const eventBase = eventName.toLowerCase();
  const endings = eventEndings[gesture];

  hash[eventBase] = eventName;
  endings.forEach((ending) => {
    const event = eventName + ending;

    hash[event.toLowerCase()] = event;
  });
}

// this function can be replaced in ember 1.13 with a private api
// and in ember 2.0 with a potentially public api matching 1.13's
// private api. This is a stop gap for pre-ember 1.13
function getModuleList() {
  /* global requirejs */
  const list = [];

  for (let moduleName in requirejs.entries) {
    if (Object.prototype.hasOwnProperty.call(requirejs.entries, moduleName)) {
      const parts = moduleName.match(/ember-gestures\/recognizers\/(.*)/);

      if (parts && parts[1].indexOf('jshint') === -1) {
        list.push(parts[1]);
      }
    }
  }
  return list;
}
<commit_msg>bugfix(rootElementResolution): fixes #118 where wrong resolution of rootElement causes  the cleanup of eventHandlers to fail and thus leads to a memory leak.<commit_after>import { getOwner } from '@ember/application';
import { merge, assign as _assign } from '@ember/polyfills';
import { get, set } from '@ember/object';
import Ember from 'ember';
import defaultHammerEvents from './hammer-events';
import dasherizedToCamel from './utils/string/dasherized-to-camel';
import mobileDetection from './utils/is-mobile';
import { isNone } from '@ember/utils';

const {
  EventDispatcher,
} = Ember;

const eventEndings = {
  pan: ['Start', 'Move', 'End', 'Cancel', 'Left', 'Right', 'Up', 'Down'],
  pinch: ['Start', 'Move', 'End', 'Cancel', 'In', 'Out'],
  press: ['Up'],
  rotate: ['Start', 'Move', 'End', 'Cancel'],
  swipe: ['Left', 'Right', 'Up', 'Down'],
  tap: []
};

const assign = _assign || merge;

const notFocusableTypes = ['submit', 'file', 'button', 'hidden', 'reset', 'range', 'radio', 'image', 'checkbox'];

const fastFocusEvents = ['click', 'touchend'];

export default EventDispatcher.extend({

  /**
   Whether or not to cache handler paths on the element
   when `useCapture` is also true.
   This needs to be replaced by a feature flag.
   @private
   @type {boolean}
   */
  useFastPaths: false,
  useCapture: false,

  _gestures: null,
  _initializeGestures() {
    const list = getModuleList();
    const events = assign({}, defaultHammerEvents);

    list.forEach((name) => {
      const recognizer = getOwner(this).factoryFor('ember-gesture:recognizers/' + name);

      if (recognizer) {
        addEvent(events, recognizer.class.recognizer, recognizer.class.eventName || name);
      }
    });

    // add them to the event dispatcher
    this.set('_gestures', events);

  },

  _fastFocus() {
    let rootElementSelector = get(this, 'rootElement');
    let rootElement;
    if (rootElementSelector.nodeType) {
      rootElement = rootElementSelector;
    } else {
      rootElement = document.querySelector(rootElementSelector);
    }

    fastFocusEvents.forEach((event) => {
      let listener = this._gestureEvents[event] = (e) => {
        if (mobileDetection.is()) {
          let element = e.currentTarget;
          let target = e.target;

          /*
           If the click was on an input element that needs to be able to focus, recast
           the click as a "focus" event.
           This fixes tap events on mobile where keyboardShrinksView or similar is true.
           Such devices depend on the ghost click to trigger focus, but the ghost click
           will never reach the element.
           */

          //fastfocus
          if (element.tagName === 'TEXTAREA' || (element.tagName === 'INPUT' && notFocusableTypes.indexOf(element.getAttribute('type')) === -1)) {
            element.focus();

          } else if (target.tagName === 'TEXTAREA' || (target.tagName === 'INPUT' && notFocusableTypes.indexOf(target.getAttribute('type')) === -1)) {
            target.focus();
          }
        }
      };
      rootElement.addEventListener(event, listener);
    });
  },

  willDestroy() {
    let rootElementSelector = get(this, 'rootElement');
    let rootElement;
    if (rootElementSelector.nodeType) {
      rootElement = rootElementSelector;
    } else {
      rootElement = document.querySelector(rootElementSelector);
    }

    if (rootElement) {
      for (let event in this._gestureEvents) {
        rootElement.removeEventListener(event, this._gestureEvents[event]);
        delete this._gestureEvents[event];
      }
    }
    this._super(...arguments);
  },

  _finalEvents: null,

  init() {
    this._gestureEvents = Object.create(null);
    this._super(...arguments);
  },

  setup(addedEvents, rootElement) {
    this._initializeGestures();
    let events = assign({}, get(this, 'events'));

    // remove undesirable events from Ember's Eventing
    if (this.get('removeTracking')) {
      events.touchstart = null;
      events.touchmove = null;
      events.touchcancel = null;
      events.touchend = null;

      events.mousedown = null;
      events.mouseenter = null;
      events.mousemove = null;
      events.mouseleave = null;
      events.mouseup = null;

      events.drag = null;
      events.dragend = null;
      events.dragenter = null;
      events.dragleave = null;
      events.dragover = null;
      events.dragstart = null;
      events.drop = null;

      events.dblclick = null;
    }

    // delete unwanted events
    for (let event in events) {
      if (events.hasOwnProperty(event) && !events[event]) {
        delete events[event];
      }
    }

    // override default events
    this.set('events', events);

    // add our events to addition events
    let additionalEvents = assign({}, addedEvents);
    additionalEvents = assign(additionalEvents, this.get('_gestures'));

    if (!isNone(rootElement)) {
      set(this, 'rootElement', rootElement);
    }

    this._fastFocus();

    return this._super(additionalEvents, rootElement);
  }

});

function addEvent(hash, gesture, name) {
  const eventName = dasherizedToCamel(name);
  const eventBase = eventName.toLowerCase();
  const endings = eventEndings[gesture];

  hash[eventBase] = eventName;
  endings.forEach((ending) => {
    const event = eventName + ending;

    hash[event.toLowerCase()] = event;
  });
}

// this function can be replaced in ember 1.13 with a private api
// and in ember 2.0 with a potentially public api matching 1.13's
// private api. This is a stop gap for pre-ember 1.13
function getModuleList() {
  /* global requirejs */
  const list = [];

  for (let moduleName in requirejs.entries) {
    if (Object.prototype.hasOwnProperty.call(requirejs.entries, moduleName)) {
      const parts = moduleName.match(/ember-gestures\/recognizers\/(.*)/);

      if (parts && parts[1].indexOf('jshint') === -1) {
        list.push(parts[1]);
      }
    }
  }
  return list;
}
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Service.extend({

  createCustomBlock(name, options, callback_to_change_block) {
    let previousStatement = true;
    let nextStatement = true;
    options.colour = options.color || '#4453ff';

    if (Blockly.Blocks[name]) {
      console.warn(`Redefiniendo el bloque ${name}`);
    }

    Blockly.Blocks[name] = {
      init: function() {
        this.jsonInit(options);

        if (callback_to_change_block) {
          callback_to_change_block.call(this);
        }

      }
    };

    Blockly.Blocks[name].isCustomBlock = true;

    if (!Blockly.MyLanguage) {
      Blockly.MyLanguage = Blockly.JavaScript;
    }

    if (options.code) {
      Blockly.MyLanguage[name] = function(block) {
        let variables = options.code.match(/\$(\w+)/g);
        let code = options.code;

        if (variables) {
          variables.forEach((v) => {
            let regex = new RegExp('\\' + v, "g");
            let variable_name = v.slice(1);

            var variable_object = Blockly.MyLanguage.valueToCode(block, variable_name) || block.getFieldValue(variable_name) || null;

            code = code.replace(regex, variable_object);
          });
        }

        return code;
      };
    }

    return Blockly.Blocks[name]
  },

  createBlockWithAsyncDropdown(name, options) {
    function callback_to_change_block() {
      this.
        appendDummyInput().
        appendField(options.label || "").
        appendField(new Blockly.FieldDropdown(options.callbackDropdown), 'DROPDOWN_VALUE');
    }

    return this.createCustomBlock(name, options, callback_to_change_block);
  },

  createCustomBlockWithHelper(name, options) {
    let color = options.color || '#4a6cd4';

    return this.createCustomBlock(name, {
      message0: `%1 ${options.descripcion}`,
      colour: color,
      previousStatement: true,
      nextStatement: true,
      args0: [
        {
          "type": "field_image",
          "src": `iconos/${options.icono}`,
          "width": 16,
          "height": 16,
          "alt": "*"
        }
      ],
      code: `hacer(actor_id, "${options.comportamiento}", ${options.argumentos});`,
    });
  },

  createBlockValue(name, options) {
    let color = options.color || '#4a6cd4';

    return this.createCustomBlock(name, {
      message0: `%1 ${options.descripcion}`,
      colour: color,
      previousStatement: true,
      nextStatement: true,
      args0: [
        {
          "type": "field_image",
          "src": `iconos/${options.icono}`,
          "width": 16,
          "height": 16,
          "alt": "*"
        }
      ],
      code: `'${options.valor}'`,
    });
  },

  getBlocksList() {
    return Object.keys(Blockly.Blocks);
  },

  getCustomBlocksList() {
    return Object.keys(Blockly.Blocks).filter((e) => {
      return Blockly.Blocks[e].isCustomBlock}
    );
  },

  createAlias(new_name, original_block_name) {
    let original_block = Blockly.Blocks[original_block_name];
    Blockly.Blocks[new_name] = Object.assign({}, original_block);
    Blockly.Blocks[new_name].isCustomBlock = true;

    if (!Blockly.MyLanguage) {
      Blockly.MyLanguage = Blockly.JavaScript;
    }

    Blockly.MyLanguage[new_name] = Blockly.JavaScript[original_block_name];

    return Blockly.Blocks[new_name];
  }
});
<commit_msg>Arreglo menor para permitir que se sobre-escriba la plantilla de codigo al generar un bloque con helper.<commit_after>import Ember from 'ember';

export default Ember.Service.extend({

  createCustomBlock(name, options, callback_to_change_block) {
    let previousStatement = true;
    let nextStatement = true;
    options.colour = options.color || '#4453ff';

    if (Blockly.Blocks[name]) {
      console.warn(`Redefiniendo el bloque ${name}`);
    }

    Blockly.Blocks[name] = {
      init: function() {
        this.jsonInit(options);

        if (callback_to_change_block) {
          callback_to_change_block.call(this);
        }

      }
    };

    Blockly.Blocks[name].isCustomBlock = true;

    if (!Blockly.MyLanguage) {
      Blockly.MyLanguage = Blockly.JavaScript;
    }

    if (options.code) {
      Blockly.MyLanguage[name] = function(block) {
        let variables = options.code.match(/\$(\w+)/g);
        let code = options.code;

        if (variables) {
          variables.forEach((v) => {
            let regex = new RegExp('\\' + v, "g");
            let variable_name = v.slice(1);

            var variable_object = Blockly.MyLanguage.valueToCode(block, variable_name) || block.getFieldValue(variable_name) || null;

            code = code.replace(regex, variable_object);
          });
        }

        return code;
      };
    }

    return Blockly.Blocks[name]
  },

  createBlockWithAsyncDropdown(name, options) {
    function callback_to_change_block() {
      this.
        appendDummyInput().
        appendField(options.label || "").
        appendField(new Blockly.FieldDropdown(options.callbackDropdown), 'DROPDOWN_VALUE');
    }

    return this.createCustomBlock(name, options, callback_to_change_block);
  },

  createCustomBlockWithHelper(name, options) {
    let color = options.color || '#4a6cd4';

    return this.createCustomBlock(name, {
      message0: `%1 ${options.descripcion}`,
      colour: color,
      previousStatement: true,
      nextStatement: true,
      args0: [
        {
          "type": "field_image",
          "src": `iconos/${options.icono}`,
          "width": 16,
          "height": 16,
          "alt": "*"
        }
      ],
      code: options.code || `hacer(actor_id, "${options.comportamiento}", ${options.argumentos});`,
    });
  },

  createBlockValue(name, options) {
    let color = options.color || '#4a6cd4';

    return this.createCustomBlock(name, {
      message0: `%1 ${options.descripcion}`,
      colour: color,
      previousStatement: true,
      nextStatement: true,
      args0: [
        {
          "type": "field_image",
          "src": `iconos/${options.icono}`,
          "width": 16,
          "height": 16,
          "alt": "*"
        }
      ],
      code: `'${options.valor}'`,
    });
  },

  getBlocksList() {
    return Object.keys(Blockly.Blocks);
  },

  getCustomBlocksList() {
    return Object.keys(Blockly.Blocks).filter((e) => {
      return Blockly.Blocks[e].isCustomBlock}
    );
  },

  createAlias(new_name, original_block_name) {
    let original_block = Blockly.Blocks[original_block_name];
    Blockly.Blocks[new_name] = Object.assign({}, original_block);
    Blockly.Blocks[new_name].isCustomBlock = true;

    if (!Blockly.MyLanguage) {
      Blockly.MyLanguage = Blockly.JavaScript;
    }

    Blockly.MyLanguage[new_name] = Blockly.JavaScript[original_block_name];

    return Blockly.Blocks[new_name];
  }
});
<|endoftext|>