////////////////////////////////////////////////////////////////////////////
//
// 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 */
/* eslint-disable no-console */

'use strict';

const fs = require('fs');
const path = require('path');
const mockery = require('mockery');

function runTests() {
    const Realm = require('realm');
    const RealmTests = require('./js');
    const testNames = RealmTests.getTestNames();
    let passed = true;

    // Create this method with appropriate implementation for Node testing.
    Realm.copyBundledRealmFiles = function() {
        let sourceDir = path.join(__dirname, 'data');
        let destinationDir = path.dirname(Realm.defaultPath);

        for (let filename of fs.readdirSync(sourceDir)) {
            let src = path.join(sourceDir, filename);
            let dest = path.join(destinationDir, filename);

            // If the destination file already exists, then don't overwrite it.
            try {
                fs.accessSync(dest);
                continue;
            } catch (e) {}

            fs.writeFileSync(dest, fs.readFileSync(src));
        }
    };

    for (let suiteName in testNames) {
        console.log('Starting ' + suiteName);

        for (let testName of testNames[suiteName]) {
            RealmTests.runTest(suiteName, 'beforeEach');

            try {
                RealmTests.runTest(suiteName, testName);
                console.log('+ ' + testName);
            }
            catch (e) {
                console.warn('- ' + testName);
                console.error(e.message, e.stack);
                passed = false;
            }
            finally {
                RealmTests.runTest(suiteName, 'afterEach');
            }
        }
    }

    return passed;
}

if (require.main == module) {
    mockery.enable();
    mockery.warnOnUnregistered(false);
    mockery.registerMock('realm', require('..'));

    if (!runTests()) {
        process.exit(1);
    }
}

@@ -1762,143 +1762,317 @@
     
-for (let suiteName in testNames) %7B%0A        console.log('Starting ' + suiteName);%0A%0A        for (let testName of testNames%5BsuiteName%5D) %7B%0A
+return Object.keys(testNames).reduce((suitePromiseChain, suiteName) =%3E %7B%0A        return suitePromiseChain.then(() =%3E %7B%0A            console.log('Starting ' + suiteName);%0A%0A            return testNames%5BsuiteName%5D.reduce((testPromiseChain, testName) =%3E %7B%0A                return testPromiseChain.then(() =%3E %7B%0A     
     
@@ -2071,32 +2071,42 @@
                 
+   return 
 RealmTests.runTe
@@ -2134,17 +2134,20 @@
 Each');%0A
-%0A
+    
         
@@ -2142,35 +2142,45 @@
                 
-try
+%7D).then(() =%3E
  %7B%0A             
@@ -2173,32 +2173,43 @@
 %0A               
+ 
+    return
  RealmTests.runT
@@ -2226,32 +2226,68 @@
 ame, testName);%0A
+                %7D).then(() =%3E %7B%0A    
                 
@@ -2332,34 +2332,30 @@
     
-%7D%0A            catch (e) %7B%0A
+    %7D, (err) =%3E %7B%0A    
     
@@ -2413,24 +2413,28 @@
         
+    
 console.
 error(e.
@@ -2429,35 +2429,38 @@
 ole.
-error(e.message, e.stack);%0A
+warn(err.message %7C%7C err);%0A    
     
@@ -2503,32 +2503,34 @@
     
-%7D%0A
     
-        finally %7B%0A
+%7D).then(() =%3E %7B%0A      
     
@@ -2539,17 +2539,22 @@
         
- 
+return
  RealmTe
@@ -2598,25 +2598,31 @@
             
-%7D
+    %7D);
 %0A        %7D%0A 
@@ -2622,34 +2622,91 @@
     
-%7D%0A    %7D%0A%0A    return
+    %7D, Promise.resolve());%0A        %7D);%0A    %7D, Promise.resolve()).then(() =%3E
  passed
+)
 ;%0A%7D%0A
@@ -2856,27 +2856,187 @@
     
-if (!runTests()) %7B%0A
+runTests().then(%0A        (passed) =%3E %7B%0A            if (!passed) %7B%0A                process.exit(1);%0A            %7D%0A        %7D,%0A        (err) =%3E %7B%0A            console.error(err);%0A    
     
@@ -3060,12 +3060,23 @@
 1);%0A    
-%7D
+    %7D%0A    );
 %0A%7D%0A

Allow Node tests to be asynchronous