<commit_before>/*
 * Checks that the links in the footer on the homepage have the right URLs to redirect to
 *
 * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows
 */

const SeleniumHelper = require('../selenium-helpers.js');
const helper = new SeleniumHelper();

const tap = require('tap');

const webdriver = require('selenium-webdriver');
const driver = helper.buildDriver('www-smoke test_footer_links');

const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';

// timeout for each test; timeout for suite set at command line level
const options = {timeout: 30000};

// number of tests in the plan
tap.plan(25);

tap.tearDown(function () {
    // quit the instance of the browser
    driver.quit();
});

tap.beforeEach(function () {
    // load the page with the driver
    return driver.get(rootUrl);
});

// Function clicks the link and returns the url of the resulting page

const clickFooterLinks = function (linkText) {
    return driver.wait(webdriver.until.elementLocated(webdriver.By.id('footer')))
        .then(function (element) {
            return element.findElement(webdriver.By.linkText(linkText));
        })
        .then(function (element) {
            return element.click();
        })
        .then(function () {
            return driver.getCurrentUrl();
        });
};

// ==== ABOUT SCRATCH column ====

// ABOUT SCRATCH
tap.test('clickAboutScratchLink', options, t => {
    const linkText = 'About Scratch';
    const expectedHref = '/about';
    clickFooterLinks(linkText).then(url => {
        // the href should be at the end of the URL
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// FOR PARENTS
tap.test('clickForParentsLink', options, t => {
    const linkText = 'For Parents';
    const expectedHref = '/parents/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// FOR EDUCATORS
tap.test('clickForEducatorsLink', options, t => {
    const linkText = 'For Educators';
    const expectedHref = '/educators';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// FOR DEVELOPERS
tap.test('clickForDevelopersScratchLink', options, t => {
    const linkText = 'For Developers';
    const expectedHref = '/developers';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// CREDITS
tap.test('clickCreditsLink', options, t => {
    const linkText = 'Credits';
    const expectedHref = '/info/credits';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// JOBS
tap.test('clickJobsLink', options, t => {
    const linkText = 'Jobs';
    const expectedHref = '/jobs';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// PRESS
tap.test('clickPressLink', options, t => {
    const linkText = 'Press';
    const expectedUrl = 'https://www.scratchfoundation.org/media-kit/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// ==== COMMUNITY column ====

// COMMUNITY GUIDELINES
tap.test('clickCommunityGuidelinesLink', options, t => {
    const linkText = 'Community Guidelines';
    const expectedHref = '/community_guidelines';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// DISCUSSION FORUMS
tap.test('clickDiscussionForumsLink', options, t => {
    const linkText = 'Discussion Forums';
    const expectedHref = '/discuss/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// SCRATCH WIKI
tap.test('clickScratchWikiLink', options, t => {
    const linkText = 'Scratch Wiki';
    const expectedUrl = 'https://en.scratch-wiki.info/wiki/Scratch_Wiki_Home';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// STATISTICS
tap.test('clickStatisticsLink', options, t => {
    const linkText = 'Statistics';
    const expectedHref = '/statistics/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// ==== SUPPORT column ====

// IDEAS PAGE
tap.test('clickIdeasPageLink', options, t => {
    const linkText = 'Ideas';
    const expectedHref = '/ideas';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// FAQ
tap.test('clickFAQLink', options, t => {
    const linkText = 'FAQ';
    const expectedHref = '/info/faq';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// OFFLINE EDITOR
tap.test('clickOfflineEditorLink', options, t => {
    const linkText = 'Offline Editor';
    const expectedHref = '/download';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// CONTACT US
tap.test('clickContactUsLink', options, t => {
    const linkText = 'Contact Us';
    const expectedHref = '/contact-us/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// SCRATCH STORE
tap.test('clickScratchStoreLink', options, t => {
    const linkText = 'Scratch Store';
    const expectedUrl = 'https://scratch-foundation.myshopify.com/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// DONATE
tap.test('clickDonateLink', options, t => {
    const linkText = 'Donate';
    const expectedUrl = 'https://secure.donationpay.org/scratchfoundation/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// ==== LEGAL column ====

// TERMS OF USE
tap.test('clickTermsOfUseLink', options, t => {
    const linkText = 'Terms of Use';
    const expectedHref = '/terms_of_use';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// PRIVACY POLICY
tap.test('clickPrivacyPolicyLink', options, t => {
    const linkText = 'Privacy Policy';
    const expectedHref = '/privacy_policy';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// DMCA
tap.test('clickDMCALink', options, t => {
    const linkText = 'DMCA';
    const expectedHref = '/DMCA';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// ==== SCRATCH FAMILY column ====

// SCRATCH ED (SCRATCHED)
tap.test('clickScratchEdLink', options, t => {
    const linkText = 'ScratchEd';
    const expectedUrl = 'http://scratched.gse.harvard.edu/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// SCRATCH JR (SCRATCHJR)
tap.test('clickScratchJrLink', options, t => {
    const linkText = 'ScratchJr';
    const expectedUrl = 'https://www.scratchjr.org/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// SCRATCH DAY
tap.test('clickScratchDayLink', options, t => {
    const linkText = 'Scratch Day';
    const expectedUrl = 'https://day.scratch.mit.edu/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// SCRATCH CONFERENCE
tap.test('clickScratchConferenceLink', options, t => {
    const linkText = 'Scratch Conference';
    const expectedHref = '/conference';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// SCRATCH FOUNDATION
tap.test('clickScratchFoundationLink', options, t => {
    const linkText = 'Scratch Foundation';
    const expectedUrl = 'https://www.scratchfoundation.org/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});
<commit_msg>Credits link has changed<commit_after>/*
 * Checks that the links in the footer on the homepage have the right URLs to redirect to
 *
 * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows
 */

const SeleniumHelper = require('../selenium-helpers.js');
const helper = new SeleniumHelper();

const tap = require('tap');

const webdriver = require('selenium-webdriver');
const driver = helper.buildDriver('www-smoke test_footer_links');

const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';

// timeout for each test; timeout for suite set at command line level
const options = {timeout: 30000};

// number of tests in the plan
tap.plan(25);

tap.tearDown(function () {
    // quit the instance of the browser
    driver.quit();
});

tap.beforeEach(function () {
    // load the page with the driver
    return driver.get(rootUrl);
});

// Function clicks the link and returns the url of the resulting page

const clickFooterLinks = function (linkText) {
    return driver.wait(webdriver.until.elementLocated(webdriver.By.id('footer')))
        .then(function (element) {
            return element.findElement(webdriver.By.linkText(linkText));
        })
        .then(function (element) {
            return element.click();
        })
        .then(function () {
            return driver.getCurrentUrl();
        });
};

// ==== ABOUT SCRATCH column ====

// ABOUT SCRATCH
tap.test('clickAboutScratchLink', options, t => {
    const linkText = 'About Scratch';
    const expectedHref = '/about';
    clickFooterLinks(linkText).then(url => {
        // the href should be at the end of the URL
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// FOR PARENTS
tap.test('clickForParentsLink', options, t => {
    const linkText = 'For Parents';
    const expectedHref = '/parents/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// FOR EDUCATORS
tap.test('clickForEducatorsLink', options, t => {
    const linkText = 'For Educators';
    const expectedHref = '/educators';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// FOR DEVELOPERS
tap.test('clickForDevelopersScratchLink', options, t => {
    const linkText = 'For Developers';
    const expectedHref = '/developers';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// CREDITS
tap.test('clickCreditsLink', options, t => {
    const linkText = 'Credits';
    const expectedHref = '/credits';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// JOBS
tap.test('clickJobsLink', options, t => {
    const linkText = 'Jobs';
    const expectedHref = '/jobs';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// PRESS
tap.test('clickPressLink', options, t => {
    const linkText = 'Press';
    const expectedUrl = 'https://www.scratchfoundation.org/media-kit/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// ==== COMMUNITY column ====

// COMMUNITY GUIDELINES
tap.test('clickCommunityGuidelinesLink', options, t => {
    const linkText = 'Community Guidelines';
    const expectedHref = '/community_guidelines';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// DISCUSSION FORUMS
tap.test('clickDiscussionForumsLink', options, t => {
    const linkText = 'Discussion Forums';
    const expectedHref = '/discuss/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// SCRATCH WIKI
tap.test('clickScratchWikiLink', options, t => {
    const linkText = 'Scratch Wiki';
    const expectedUrl = 'https://en.scratch-wiki.info/wiki/Scratch_Wiki_Home';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// STATISTICS
tap.test('clickStatisticsLink', options, t => {
    const linkText = 'Statistics';
    const expectedHref = '/statistics/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// ==== SUPPORT column ====

// IDEAS PAGE
tap.test('clickIdeasPageLink', options, t => {
    const linkText = 'Ideas';
    const expectedHref = '/ideas';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// FAQ
tap.test('clickFAQLink', options, t => {
    const linkText = 'FAQ';
    const expectedHref = '/info/faq';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// OFFLINE EDITOR
tap.test('clickOfflineEditorLink', options, t => {
    const linkText = 'Offline Editor';
    const expectedHref = '/download';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// CONTACT US
tap.test('clickContactUsLink', options, t => {
    const linkText = 'Contact Us';
    const expectedHref = '/contact-us/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// SCRATCH STORE
tap.test('clickScratchStoreLink', options, t => {
    const linkText = 'Scratch Store';
    const expectedUrl = 'https://scratch-foundation.myshopify.com/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// DONATE
tap.test('clickDonateLink', options, t => {
    const linkText = 'Donate';
    const expectedUrl = 'https://secure.donationpay.org/scratchfoundation/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// ==== LEGAL column ====

// TERMS OF USE
tap.test('clickTermsOfUseLink', options, t => {
    const linkText = 'Terms of Use';
    const expectedHref = '/terms_of_use';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// PRIVACY POLICY
tap.test('clickPrivacyPolicyLink', options, t => {
    const linkText = 'Privacy Policy';
    const expectedHref = '/privacy_policy';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// DMCA
tap.test('clickDMCALink', options, t => {
    const linkText = 'DMCA';
    const expectedHref = '/DMCA';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// ==== SCRATCH FAMILY column ====

// SCRATCH ED (SCRATCHED)
tap.test('clickScratchEdLink', options, t => {
    const linkText = 'ScratchEd';
    const expectedUrl = 'http://scratched.gse.harvard.edu/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// SCRATCH JR (SCRATCHJR)
tap.test('clickScratchJrLink', options, t => {
    const linkText = 'ScratchJr';
    const expectedUrl = 'https://www.scratchjr.org/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// SCRATCH DAY
tap.test('clickScratchDayLink', options, t => {
    const linkText = 'Scratch Day';
    const expectedUrl = 'https://day.scratch.mit.edu/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});

// SCRATCH CONFERENCE
tap.test('clickScratchConferenceLink', options, t => {
    const linkText = 'Scratch Conference';
    const expectedHref = '/conference';
    clickFooterLinks(linkText).then(url => {
        t.equal(url.substr(-expectedHref.length), expectedHref);
        t.end();
    });
});

// SCRATCH FOUNDATION
tap.test('clickScratchFoundationLink', options, t => {
    const linkText = 'Scratch Foundation';
    const expectedUrl = 'https://www.scratchfoundation.org/';
    clickFooterLinks(linkText).then(url => {
        t.equal(url, expectedUrl);
        t.end();
    });
});
<|endoftext|>


<commit_before>'use strict'

/*global describe, beforeEach, it*/

var expect = require('chai').expect
var angular = require('angular')
require('angular-mocks')

describe('cc-cvc', function () {
  beforeEach(angular.mock.module(require('../')))

  var $compile, scope, controller, element
  beforeEach(angular.mock.inject(function ($injector) {
    $compile = $injector.get('$compile')
    scope = $injector.get('$rootScope').$new()
    scope.card = {}
    element = angular.element('<input ng-model="card.cvc" cc-cvc />')
    controller = $compile(element)(scope).controller('ngModel')
  }))

  it('sets maxlength to 4', function () {
    expect(element.attr('maxlength')).to.equal('4')
  })

  it('adds a numeric pattern', function () {
    expect(element.attr('pattern')).to.equal('[0-9]*')
  })

  it('adds an autocomplete attribute', function () {
    expect(element.attr('x-autocompletetype')).to.equal('cc-csc')
  })

  it('accepts a 3 digit numeric', function () {
    controller.$setViewValue('123')
    scope.$digest()
    expect(controller.$valid).to.be.true
    expect(scope.card.cvc).to.equal('123')
  })

  it('accepts a 4 digit numeric', function () {
    controller.$setViewValue('1234')
    scope.$digest()
    expect(controller.$valid).to.be.true
    expect(scope.card.cvc).to.equal('1234')
  })

  it('does not accept numbers', function () {
    controller.$setViewValue(123)
    scope.$digest()
    expect(controller.$valid).to.be.false
  })

  it('unsets the model value when invalid', function () {
    controller.$setViewValue('abc')
    scope.$digest()
    expect(scope.card.cvc).to.be.undefined
  })

  describe('ccType', function () {
    beforeEach(function () {
      element.attr('cc-type', 'cardType')
      controller = $compile(element)(scope).controller('ngModel')
    })

    it('validates against the card type', function () {
      scope.cardType = 'visa'
      scope.card.cvc = '1234'
      scope.$digest()
      expect(controller.$valid).to.be.false
      scope.cardType = 'americanExpress'
      scope.$digest()
      expect(controller.$valid).to.be.true
    })

  })

})
<commit_msg>Add ngMocks to cvc tests<commit_after>'use strict'

/*global describe, beforeEach, it*/

var expect = require('chai').expect
var angular = require('angular')
require('angular-mocks/ngMock')

describe('cc-cvc', function () {
  beforeEach(angular.mock.module(require('../')))

  var $compile, scope, controller, element
  beforeEach(angular.mock.inject(function ($injector) {
    $compile = $injector.get('$compile')
    scope = $injector.get('$rootScope').$new()
    scope.card = {}
    element = angular.element('<input ng-model="card.cvc" cc-cvc />')
    controller = $compile(element)(scope).controller('ngModel')
  }))

  it('sets maxlength to 4', function () {
    expect(element.attr('maxlength')).to.equal('4')
  })

  it('adds a numeric pattern', function () {
    expect(element.attr('pattern')).to.equal('[0-9]*')
  })

  it('adds an autocomplete attribute', function () {
    expect(element.attr('x-autocompletetype')).to.equal('cc-csc')
  })

  it('accepts a 3 digit numeric', function () {
    controller.$setViewValue('123')
    scope.$digest()
    expect(controller.$valid).to.be.true
    expect(scope.card.cvc).to.equal('123')
  })

  it('accepts a 4 digit numeric', function () {
    controller.$setViewValue('1234')
    scope.$digest()
    expect(controller.$valid).to.be.true
    expect(scope.card.cvc).to.equal('1234')
  })

  it('does not accept numbers', function () {
    controller.$setViewValue(123)
    scope.$digest()
    expect(controller.$valid).to.be.false
  })

  it('unsets the model value when invalid', function () {
    controller.$setViewValue('abc')
    scope.$digest()
    expect(scope.card.cvc).to.be.undefined
  })

  describe('ccType', function () {
    beforeEach(function () {
      element.attr('cc-type', 'cardType')
      controller = $compile(element)(scope).controller('ngModel')
    })

    it('validates against the card type', function () {
      scope.cardType = 'visa'
      scope.card.cvc = '1234'
      scope.$digest()
      expect(controller.$valid).to.be.false
      scope.cardType = 'americanExpress'
      scope.$digest()
      expect(controller.$valid).to.be.true
    })

  })

})
<|endoftext|>


<commit_before>const Selector = require('selector_manager/model/Selector');
const Selectors = require('selector_manager/model/Selectors');

module.exports = {
  run() {
      describe('Selector', () => {
        var obj;

        beforeEach(() => {
          obj  = new Selector();
        });

        afterEach(() => {
          obj = null;
        });

        it('Has name property', () => {
          expect(obj.has('name')).toEqual(true);
        });

        it('Has label property', () => {
          expect(obj.has('label')).toEqual(true);
        });

        it('Has active property', () => {
          expect(obj.has('active')).toEqual(true);
        });

        it('escapeName test', () => {
          expect(Selector.escapeName('@Te sT*')).toEqual('-Te-sT-');
        });

        it('Name is corrected at instantiation', () => {
          obj  = new Selector({ name: '@Te sT*'});
          expect(obj.get('name')).toEqual('-Te-sT-');
        });

    });
    describe('Selectors', () => {

        it('Creates collection item correctly', () => {
          var c = new Selectors();
          var m = c.add({});
          expect(m instanceof Selector).toEqual(true);
        });

    });
  }
};
<commit_msg>Add tests for `getFullString` in Selectors<commit_after>const Selector = require('selector_manager/model/Selector');
const Selectors = require('selector_manager/model/Selectors');

module.exports = {
  run() {
      describe('Selector', () => {
        var obj;

        beforeEach(() => {
          obj  = new Selector();
        });

        afterEach(() => {
          obj = null;
        });

        it('Has name property', () => {
          expect(obj.has('name')).toEqual(true);
        });

        it('Has label property', () => {
          expect(obj.has('label')).toEqual(true);
        });

        it('Has active property', () => {
          expect(obj.has('active')).toEqual(true);
        });

        it('escapeName test', () => {
          expect(Selector.escapeName('@Te sT*')).toEqual('-Te-sT-');
        });

        it('Name is corrected at instantiation', () => {
          obj  = new Selector({ name: '@Te sT*'});
          expect(obj.get('name')).toEqual('-Te-sT-');
        });

    });

    describe.only('Selectors', () => {
        var obj;

        beforeEach(() => {
          obj = new Selectors();
        });

        it('Creates collection item correctly', () => {
          var c = new Selectors();
          var m = c.add({});
          expect(m instanceof Selector).toEqual(true);
        });

        it('getFullString with single class', () => {
          obj.add({name: 'test'});
          expect(obj.getFullString()).toEqual('.test');
        });

        it('getFullString with multiple classes', () => {
          obj.add([{name: 'test'}, {name: 'test2'}]);
          expect(obj.getFullString()).toEqual('.test.test2');
        });

        it('getFullString with mixed selectors', () => {
          obj.add([{name: 'test'}, {name: 'test2', type: Selector.TYPE_ID}]);
          expect(obj.getFullString()).toEqual('.test#test2');
        });

    });
  }
};
<|endoftext|>


<commit_before>test("Error constructor works", function() {
  var e = new Error();
  assert_equal(e.name, "Error");
  assert_equal(e.message, undefined);

  var f = new Error("test");
  assert_equal(f.name, "Error");
  assert_equal(f.message, "test");
});

test("json parser works with simple values", function() {
    assert_equal(123, JSON.parse("123"));
    assert_equal(123.456, JSON.parse("123.456"));
    assert_equal(-123456, JSON.parse("-123.456e3"));
    assert_equal(true, JSON.parse("true"));
    assert_equal(false, JSON.parse("false"));
    assert_equal(null, JSON.parse("null"));
    assert_equal("foo", JSON.parse('"foo"'));
    assert_equal("", JSON.parse('""'));
});

test("json parser works with arrays", function() {
    var a = JSON.parse("[1,2,3]");
    assert_equal(3, a.length);
    assert_equal(1, a[0]);
    assert_equal(2, a[1]);
    assert_equal(3, a[2]);

    var a = JSON.parse("[[[[1]]]]");
    assert_equal(1, a.length);
    assert_equal(1, a[0][0][0][0]);
});

test("json parser works with object", function() {
    var o = JSON.parse('{ "a": 1, "b": [2] }');
    assert_equal(1, o.a);
    assert_equal(1, o.b.length);
    assert_equal(2, o.b[0]);

    var o = JSON.parse('{"a":{"b":{"a":{"b":123}}}}');
    assert_equal(123, o.a.b.a.b);
});<commit_msg>JSON.stringify test cases<commit_after>test("Error constructor works", function() {
  var e = new Error();
  assert_equal(e.name, "Error");
  assert_equal(e.message, undefined);

  var f = new Error("test");
  assert_equal(f.name, "Error");
  assert_equal(f.message, "test");
});

test("json parser works with simple values", function() {
    assert_equal(123, JSON.parse("123"));
    assert_equal(123.456, JSON.parse("123.456"));
    assert_equal(-123456, JSON.parse("-123.456e3"));
    assert_equal(true, JSON.parse("true"));
    assert_equal(false, JSON.parse("false"));
    assert_equal(null, JSON.parse("null"));
    assert_equal("foo", JSON.parse('"foo"'));
    assert_equal("", JSON.parse('""'));
});

test("json parser works with arrays", function() {
    var a = JSON.parse("[1,2,3]");
    assert_equal(3, a.length);
    assert_equal(1, a[0]);
    assert_equal(2, a[1]);
    assert_equal(3, a[2]);

    var a = JSON.parse("[[[[1]]]]");
    assert_equal(1, a.length);
    assert_equal(1, a[0][0][0][0]);
});

test("json parser works with object", function() {
    var o = JSON.parse('{ "a": 1, "b": [2] }');
    assert_equal(1, o.a);
    assert_equal(1, o.b.length);
    assert_equal(2, o.b[0]);

    var o = JSON.parse('{"a":{"b":{"a":{"b":123}}}}');
    assert_equal(123, o.a.b.a.b);
});

test("json stringifer", function() {
    assert_equal("123", JSON.stringify(123));
    assert_equal("123.456", JSON.stringify(123.456));
    assert_equal("-123456", JSON.stringify(-123.456e3));
    assert_equal("true", JSON.stringify(true));
    assert_equal("false", JSON.stringify(false));
    assert_equal("null", JSON.stringify(null));
    assert_equal('"foo"', JSON.stringify("foo"));
    assert_equal('""', JSON.stringify(""));
});

test("json parser works with arrays", function() {
    assert_equal("[1,2,3]", JSON.stringify([1,2,3]));
    assert_equal("[[[[1]]]]", JSON.stringify([[[[1]]]]));
});

test("json parser works with object", function() {
    assert_equal('{"a":1,"b":[2]}', JSON.stringify({ a: 1, b: [2] }));
    assert_equal('{"a":{"b":{"a":{"b":123}}}}', JSON.stringify({a:{b:{a:{b:123}}}}));
});<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe, before, after, it */

const mockery = require('mockery')
const {mount, shallow} = require('enzyme')
const sinon = require('sinon')
const assert = require('assert')
const Immutable = require('immutable')
const config = require('../../../../../js/constants/config')
let MessageBox, appActions
require('../../../braveUnit')

describe('MessageBox component unit tests', function () {
  before(function () {
    mockery.enable({
      warnOnReplace: false,
      warnOnUnregistered: false,
      useCleanCache: true
    })
    mockery.registerMock('electron', require('../../../lib/fakeElectron'))
    MessageBox = require('../../../../../app/renderer/components/messageBox')
    appActions = require('../../../../../js/actions/appActions')
  })
  after(function () {
    mockery.disable()
  })

  const tabId = 1
  const detail1 = {
    title: 'An embedded page at brave.com says:',
    message: 'Example message',
    buttons: ['OK', 'Cancel'],
    cancelId: 1,
    suppress: true,
    showSuppress: true
  }

  describe('Object properties', function () {
    describe('tabId', function () {
      it('binds the text from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.tabId, tabId)
      })

      it('defaults to "" if detail has falsey value', function () {
        const wrapper = shallow(
          <MessageBox
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.tabId, '')
      })
    })

    describe('title', function () {
      it('binds the text from the detail object', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.title = 'example title'
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.title, detail2.title)
      })

      it('defaults to "" if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.title = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.title, '')
      })

      it('replaces the Brave extensionId with "Brave"', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.title = config.braveExtensionId + ' says:'
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.title, 'Brave says:')
      })
    })

    describe('message', function () {
      it('binds the text from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.message, detail1.message)
      })

      it('defaults to "" if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.message = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.message, '')
      })
    })

    describe('buttons', function () {
      it('binds the buttons from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.deepEqual(instance.buttons.toJS(), detail1.buttons)
      })

      it('defaults to "[OK]" if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.buttons = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.deepEqual(instance.buttons.toJS(), ['OK'])
      })
    })

    describe('cancelId', function () {
      it('binds the cancelId from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.cancelId, detail1.cancelId)
      })

      it('does not have a default if value is falsey', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.cancelId = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.cancelId, undefined)
      })
    })

    describe('suppress', function () {
      it('binds the suppress from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.suppress, detail1.suppress)
      })

      it('defaults to false if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.suppress = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.suppress, false)
      })
    })

    describe('showSuppress', function () {
      it('binds the showSuppress from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.showSuppress, detail1.showSuppress)
      })

      it('defaults to false if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.showSuppress = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.showSuppress, false)
      })
    })
  })

  describe('Rendering', function () {
    it('renders itself inside a dialog component', function () {
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      assert.equal(wrapper.find('div.dialog').length, 1)
    })

    it('renders the suppress checkbox if showSuppress is true', function () {
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      assert.equal(wrapper.find('div.switchControl').length, 1)
    })

    it('hides the suppress checkbox if showSuppress is false', function () {
      const detail2 = Object.assign({}, detail1)
      detail2.showSuppress = false
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail2)}
        />
      )
      assert.equal(wrapper.find('div.switchControl').length, 0)
    })

    it('renders the button index 0 as primaryButton', function () {
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      assert.equal(wrapper.find('button[data-l10n-id="OK"].primaryButton').length, 1)
    })

    it('renders the button index 1 as whiteButton', function () {
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      assert.equal(wrapper.find('button[data-l10n-id="Cancel"].whiteButton').length, 1)
    })
  })

  describe('Events', function () {
    it('calls appActions.tabMessageBoxUpdated when SwitchControl is toggled', function () {
      const spy = sinon.spy(appActions, 'tabMessageBoxUpdated')
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      wrapper.find('.switchBackground').simulate('click')
      assert.equal(spy.calledOnce, true)
      appActions.tabMessageBoxUpdated.restore()
    })

    it('calls appActions.tabMessageBoxDismissed with result=true when OK is clicked', function () {
      const spy = sinon.spy(appActions, 'tabMessageBoxDismissed')
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      const response = {
        suppress: detail1.suppress,
        result: true
      }
      wrapper.find('button[data-l10n-id="OK"].primaryButton').simulate('click')
      assert.equal(spy.withArgs(tabId, response).calledOnce, true)
      appActions.tabMessageBoxDismissed.restore()
    })

    it('calls appActions.tabMessageBoxDismissed with result=false when cancel is clicked', function () {
      const spy = sinon.spy(appActions, 'tabMessageBoxDismissed')
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      const response = {
        suppress: detail1.suppress,
        result: false
      }
      wrapper.find('button[data-l10n-id="Cancel"].whiteButton').simulate('click')
      assert.equal(spy.withArgs(tabId, response).calledOnce, true)
      appActions.tabMessageBoxDismissed.restore()
    })
  })
})
<commit_msg>Fix for unit test; I unintentionally had broke this after localizing alert buttons<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe, before, after, it */

const mockery = require('mockery')
const {mount, shallow} = require('enzyme')
const sinon = require('sinon')
const assert = require('assert')
const Immutable = require('immutable')
const config = require('../../../../../js/constants/config')
let MessageBox, appActions
require('../../../braveUnit')

describe('MessageBox component unit tests', function () {
  before(function () {
    mockery.enable({
      warnOnReplace: false,
      warnOnUnregistered: false,
      useCleanCache: true
    })
    mockery.registerMock('electron', require('../../../lib/fakeElectron'))
    MessageBox = require('../../../../../app/renderer/components/messageBox')
    appActions = require('../../../../../js/actions/appActions')
  })
  after(function () {
    mockery.disable()
  })

  const tabId = 1
  const detail1 = {
    title: 'An embedded page at brave.com says:',
    message: 'Example message',
    buttons: ['OK', 'Cancel'],
    cancelId: 1,
    suppress: true,
    showSuppress: true
  }

  describe('Object properties', function () {
    describe('tabId', function () {
      it('binds the text from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.tabId, tabId)
      })

      it('defaults to "" if detail has falsey value', function () {
        const wrapper = shallow(
          <MessageBox
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.tabId, '')
      })
    })

    describe('title', function () {
      it('binds the text from the detail object', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.title = 'example title'
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.title, detail2.title)
      })

      it('defaults to "" if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.title = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.title, '')
      })

      it('replaces the Brave extensionId with "Brave"', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.title = config.braveExtensionId + ' says:'
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.title, 'Brave says:')
      })
    })

    describe('message', function () {
      it('binds the text from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.message, detail1.message)
      })

      it('defaults to "" if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.message = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.message, '')
      })
    })

    describe('buttons', function () {
      it('binds the buttons from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.deepEqual(instance.buttons.toJS(), detail1.buttons)
      })

      it('defaults to "[OK]" if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.buttons = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.deepEqual(instance.buttons.toJS(), ['ok'])
      })
    })

    describe('cancelId', function () {
      it('binds the cancelId from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.cancelId, detail1.cancelId)
      })

      it('does not have a default if value is falsey', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.cancelId = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.cancelId, undefined)
      })
    })

    describe('suppress', function () {
      it('binds the suppress from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.suppress, detail1.suppress)
      })

      it('defaults to false if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.suppress = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.suppress, false)
      })
    })

    describe('showSuppress', function () {
      it('binds the showSuppress from the detail object', function () {
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail1)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.showSuppress, detail1.showSuppress)
      })

      it('defaults to false if detail has falsey value', function () {
        const detail2 = Object.assign({}, detail1)
        detail2.showSuppress = undefined
        const wrapper = shallow(
          <MessageBox
            tabId={tabId}
            detail={Immutable.fromJS(detail2)}
          />
        )
        const instance = wrapper.instance()
        assert.equal(instance.showSuppress, false)
      })
    })
  })

  describe('Rendering', function () {
    it('renders itself inside a dialog component', function () {
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      assert.equal(wrapper.find('div.dialog').length, 1)
    })

    it('renders the suppress checkbox if showSuppress is true', function () {
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      assert.equal(wrapper.find('div.switchControl').length, 1)
    })

    it('hides the suppress checkbox if showSuppress is false', function () {
      const detail2 = Object.assign({}, detail1)
      detail2.showSuppress = false
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail2)}
        />
      )
      assert.equal(wrapper.find('div.switchControl').length, 0)
    })

    it('renders the button index 0 as primaryButton', function () {
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      assert.equal(wrapper.find('button[data-l10n-id="OK"].primaryButton').length, 1)
    })

    it('renders the button index 1 as whiteButton', function () {
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      assert.equal(wrapper.find('button[data-l10n-id="Cancel"].whiteButton').length, 1)
    })
  })

  describe('Events', function () {
    it('calls appActions.tabMessageBoxUpdated when SwitchControl is toggled', function () {
      const spy = sinon.spy(appActions, 'tabMessageBoxUpdated')
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      wrapper.find('.switchBackground').simulate('click')
      assert.equal(spy.calledOnce, true)
      appActions.tabMessageBoxUpdated.restore()
    })

    it('calls appActions.tabMessageBoxDismissed with result=true when OK is clicked', function () {
      const spy = sinon.spy(appActions, 'tabMessageBoxDismissed')
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      const response = {
        suppress: detail1.suppress,
        result: true
      }
      wrapper.find('button[data-l10n-id="OK"].primaryButton').simulate('click')
      assert.equal(spy.withArgs(tabId, response).calledOnce, true)
      appActions.tabMessageBoxDismissed.restore()
    })

    it('calls appActions.tabMessageBoxDismissed with result=false when cancel is clicked', function () {
      const spy = sinon.spy(appActions, 'tabMessageBoxDismissed')
      const wrapper = mount(
        <MessageBox
          tabId={tabId}
          detail={Immutable.fromJS(detail1)}
        />
      )
      const response = {
        suppress: detail1.suppress,
        result: false
      }
      wrapper.find('button[data-l10n-id="Cancel"].whiteButton').simulate('click')
      assert.equal(spy.withArgs(tabId, response).calledOnce, true)
      appActions.tabMessageBoxDismissed.restore()
    })
  })
})
<|endoftext|>


<commit_before><commit_msg>Update amenities.js<commit_after><|endoftext|>


<commit_before>"use strict";

/* https://github.com/angular/protractor/blob/master/docs/getting-started.md */

describe("FM", function() {

    var scrollTo = function scrollTo (y) {
        return "angular.element(document).find('ng-view')[0].scrollTop =" + y;
    };

    describe("playlist", function() {
        beforeEach(function(){
            browser.get("http://127.0.0.1:8000/");
            browser.waitForAngular();
            browser.driver.sleep(2000);
        });

        it("should render playlist partial when user navigates to /", function() {
            expect(element.all(by.repeater("track in playlist")).count()).toEqual(4);
        });
    });

    describe("history", function() {

        beforeEach(function(){
            browser.manage().deleteAllCookies();
            browser.get("http://127.0.0.1:8000/history");
            browser.waitForAngular();
            browser.driver.sleep(2000);
        });

        it("should render history partial when user navigates to /history", function() {
            expect(element.all(by.repeater("track in history")).count()).toEqual(20);
        });

        it("should load more pages on scroll to bottom of list", function() {

            // confirm initial state
            expect(element.all(by.repeater("track in history")).count()).toEqual(20);

            // 2nd page
            browser.executeScript(scrollTo(2000));
            browser.driver.sleep(2000);

            expect(element.all(by.repeater("track in history")).count()).toEqual(40);

            // 3rd page
            browser.executeScript(scrollTo(4000));
            browser.driver.sleep(2000);

            expect(element.all(by.repeater("track in history")).count()).toEqual(60);

            // 4th page
            browser.executeScript(scrollTo(6000));
            browser.driver.sleep(2000);

            expect(element.all(by.repeater("track in history")).count()).toEqual(80);

            // 5th page - shouldn't exist
            browser.executeScript(scrollTo(8000));
            browser.driver.sleep(2000);

            expect(element.all(by.repeater("track in history")).count()).toEqual(80);
        });

    });

});
<commit_msg>track timer e2e test<commit_after>"use strict";

/* https://github.com/angular/protractor/blob/master/docs/getting-started.md */

describe("FM", function() {

    var scrollTo = function scrollTo (y) {
        return "angular.element(document).find('ng-view')[0].scrollTop =" + y;
    };

    describe("playlist", function() {
        beforeEach(function(){
            browser.get("http://127.0.0.1:8000/");
            browser.waitForAngular();
            browser.driver.sleep(2000);
        });

        it("should render playlist partial when user navigates to /", function() {
            expect(element.all(by.repeater("track in playlist")).count()).toEqual(4);
        });
    });

    describe("history", function() {

        beforeEach(function(){
            browser.manage().deleteAllCookies();
            browser.get("http://127.0.0.1:8000/history");
            browser.waitForAngular();
            browser.driver.sleep(2000);
        });

        it("should render history partial when user navigates to /history", function() {
            expect(element.all(by.repeater("track in history")).count()).toEqual(20);
        });

        it("should load more pages on scroll to bottom of list", function() {

            // confirm initial state
            expect(element.all(by.repeater("track in history")).count()).toEqual(20);

            // 2nd page
            browser.executeScript(scrollTo(2000));
            browser.driver.sleep(2000);

            expect(element.all(by.repeater("track in history")).count()).toEqual(40);

            // 3rd page
            browser.executeScript(scrollTo(4000));
            browser.driver.sleep(2000);

            expect(element.all(by.repeater("track in history")).count()).toEqual(60);

            // 4th page
            browser.executeScript(scrollTo(6000));
            browser.driver.sleep(2000);

            expect(element.all(by.repeater("track in history")).count()).toEqual(80);

            // 5th page - shouldn't exist
            browser.executeScript(scrollTo(8000));
            browser.driver.sleep(2000);

            expect(element.all(by.repeater("track in history")).count()).toEqual(80);
        });

    });

    describe("track timer", function() {

        var elapsedTime = 0;

        beforeEach(function(){
            browser.driver.manage().window().setSize(1630, 800);
            browser.get("http://127.0.0.1:8000/");
            browser.waitForAngular();
            browser.driver.sleep(2000);
        });

        it("should start track timer with current elapsed time", function() {
            element(by.css("footer fm-track .progress-bar")).getAttribute("aria-valuenow").then(function(value){
                expect(value > 5000).toBeTruthy();
            });
        });

        it("should increment elapsed time", function() {
            var startProgressWidth = 0;
            var startTime = 0;
            element(by.css("footer fm-track .progress-bar")).getCssValue("width").then(function(width){
                startProgressWidth = parseInt(width);
            });
            element(by.css("footer fm-track .progress-bar")).getAttribute("aria-valuenow").then(function(value){
                startTime = parseInt(value);
            });
            browser.driver.sleep(5000);

            // check elapsed time value in progress bar
            element(by.css("footer fm-track .progress-bar")).getAttribute("aria-valuenow").then(function(value){
                expect(parseInt(value) > startTime).toBeTruthy();
            });
            // check width of progress bar has increased
            element(by.css("footer fm-track .progress-bar")).getCssValue("width").then(function(width){
                expect(parseInt(width) > startProgressWidth).toBeTruthy();
            });

        });

        it("should pause and resume", function() {

            // pause
            element(by.css(".controls button:nth-child(2)")).click();

            var startTime = 0;
            element(by.css("footer fm-track .progress-bar")).getAttribute("aria-valuenow").then(function(value){
                startTime = value;
            });

            browser.driver.sleep(2000);

            element(by.css("footer fm-track .progress-bar")).getAttribute("aria-valuenow").then(function(value){
                expect(value).toEqual(startTime);
            });

            // resume
            element(by.css(".controls button:nth-child(1)")).click();
            browser.driver.sleep(2000);

            element(by.css("footer fm-track .progress-bar")).getAttribute("aria-valuenow").then(function(value){
                expect(value > startTime).toBeTruthy();
            });
        });

    });

});
<|endoftext|>


<commit_before><commit_msg>update config<commit_after>module.exports = {}
<|endoftext|>


<commit_before>var dialogPolyfill = (function() {

  var addEventListenerFn = (window.document.addEventListener
      ? function(element, type, fn) { element.addEventListener(type, fn); }
      : function(element, type, fn) { element.attachEvent('on' + type, fn); });
  var removeEventListenerFn = (window.document.removeEventListener
      ? function(element, type, fn) { element.removeEventListener(type, fn); }
      : function(element, type, fn) { element.detachEvent('on' + type, fn); });

  var dialogPolyfill = {};

  dialogPolyfill.reposition = function(element) {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
    element.style.top = topValue + 'px';
    element.dialogPolyfillInfo.isTopOverridden = true;
  };

  dialogPolyfill.inNodeList = function(nodeList, node) {
    for (var i = 0; i < nodeList.length; ++i) {
      if (nodeList[i] == node)
        return true;
    }
    return false;
  };

  dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
    for (var i = 0; i < document.styleSheets.length; ++i) {
      var styleSheet = document.styleSheets[i];
      var cssRules = null;
      // Some browsers throw on cssRules.
      try {
        cssRules = styleSheet.cssRules;
      } catch (e) {}
      if (!cssRules)
        continue;
      for (var j = 0; j < cssRules.length; ++j) {
        var rule = cssRules[j];
        var selectedNodes = null;
        // Ignore errors on invalid selector texts.
        try {
          selectedNodes = document.querySelectorAll(rule.selectorText);
        } catch(e) {}
        if (!selectedNodes || !dialogPolyfill.inNodeList(selectedNodes, element))
          continue;
        var cssTop = rule.style.getPropertyValue('top');
        var cssBottom = rule.style.getPropertyValue('bottom');
        if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
          return true;
      }
    }
    return false;
  };

  dialogPolyfill.needsCentering = function(dialog) {
    var computedStyle = getComputedStyle(dialog);
    if (computedStyle.position != 'absolute')
      return false;

    // We must determine whether the top/bottom specified value is non-auto.  In
    // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
    // Firefox returns the used value. So we do this crazy thing instead: check
    // the inline style and then go through CSS rules.
    if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
        (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
      return false;
    return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
  };

  dialogPolyfill.showDialog = function(isModal) {
    if (this.open) {
      throw 'InvalidStateError: showDialog called on open dialog';
    }
    this.open = true;
    this.setAttribute('open', 'open');

    // Find element with `autofocus` attribute or first form control
    var first_form_ctrl = null;
    var autofocus = null;
    var findElementToFocus = function(root) {
      for (var i = 0; i < root.children.length; i++) {
        var elem = root.children[i];
        if (first_form_ctrl === null && !elem.disabled && (
            elem.nodeName == 'BUTTON' ||
            elem.nodeName == 'INPUT'  ||
            elem.nodeName == 'KEYGEN' ||
            elem.nodeName == 'SELECT' ||
            elem.nodeName == 'TEXTAREA')) {
          first_form_ctrl = elem;
        }
        if (elem.autofocus) {
          autofocus = elem;
          return;
        }
        findElementToFocus(elem);
        if (autofocus !== null) return;
      }
    };

    findElementToFocus(this);

    if (autofocus !== null) {
      autofocus.focus();
    } else if (first_form_ctrl !== null) {
      first_form_ctrl.focus();
    }

    if (dialogPolyfill.needsCentering(this))
      dialogPolyfill.reposition(this);
    if (isModal) {
      this.dialogPolyfillInfo.modal = true;
      dialogPolyfill.dm.pushDialog(this);
    }
  };

  dialogPolyfill.close = function(retval) {
    if (!this.open)
      throw new InvalidStateError;
    this.open = false;
    this.removeAttribute('open');

    // Leave returnValue untouched in case it was set directly on the element
    if (typeof retval != 'undefined') {
      this.returnValue = retval;
    }

    // This won't match the native <dialog> exactly because if the user sets top
    // on a centered polyfill dialog, that top gets thrown away when the dialog is
    // closed. Not sure it's possible to polyfill this perfectly.
    if (this.dialogPolyfillInfo.isTopOverridden) {
      this.style.top = 'auto';
    }

    if (this.dialogPolyfillInfo.modal) {
      dialogPolyfill.dm.removeDialog(this);
    }

    // Triggering "close" event for any attached listeners on the <dialog>
    var event;
    if (document.createEvent) {
      event = document.createEvent('HTMLEvents');
      event.initEvent('close', true, true);
    } else {
      event = new Event('close');
    }
    this.dispatchEvent(event);

    return this.returnValue;
  };

  dialogPolyfill.registerDialog = function(element) {
    if (element.show) {
      console.warn("This browser already supports <dialog>, the polyfill " +
          "may not work correctly.");
    }
    addEventListenerFn(element, 'dialog_submit', function(e) {
      element.close(e.detail.target.value);
      e.preventDefault();
      e.stopPropagation();
    });
    element.show = dialogPolyfill.showDialog.bind(element, false);
    element.showModal = dialogPolyfill.showDialog.bind(element, true);
    element.close = dialogPolyfill.close.bind(element);
    element.dialogPolyfillInfo = {};
  };

  // The overlay is used to simulate how a modal dialog blocks the document. The
  // blocking dialog is positioned on top of the overlay, and the rest of the
  // dialogs on the pending dialog stack are positioned below it. In the actual
  // implementation, the modal dialog stacking is controlled by the top layer,
  // where z-index has no effect.
  TOP_LAYER_ZINDEX = 100000;
  MAX_PENDING_DIALOGS = 100000;

  dialogPolyfill.DialogManager = function() {
    this.pendingDialogStack = [];
    this.overlay = document.createElement('div');
    this.overlay.style.width = '100%';
    this.overlay.style.height = '100%';
    this.overlay.style.position = 'fixed';
    this.overlay.style.left = '0px';
    this.overlay.style.top = '0px';
    this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

    addEventListenerFn(this.overlay, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      document.body.dispatchEvent(redirectedEvent);
    });
    addEventListenerFn(window, 'load', function() {
      var forms = document.getElementsByTagName('form');
      Array.prototype.forEach.call(forms, function(form) {
        if (form.getAttribute('method') == 'dialog') { // form.method won't return 'dialog'
          addEventListenerFn(form, 'click', function(e) {
            if (e.target.type == 'submit') {
              var event;
              if (CustomEvent) {
                event = new CustomEvent('dialog_submit', {
                  bubbles:  true,
                  detail:   { target: e.target }
                });
              } else {
                event = document.createEvent('HTMLEvents');
                event.initEvent('dialog_submit', true, true);
                event.detail = {target: e.target};
              }
              this.dispatchEvent(event);
              e.preventDefault();
            }
          });
        }
      });
    })
  };

  dialogPolyfill.dm = new dialogPolyfill.DialogManager();

  dialogPolyfill.DialogManager.prototype.blockDocument = function() {
    if (!document.body.contains(this.overlay))
      document.body.appendChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
    document.body.removeChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.updateStacking = function() {
    if (this.pendingDialogStack.length == 0) {
      this.unblockDocument();
      return;
    }
    this.blockDocument();

    var zIndex = TOP_LAYER_ZINDEX;
    for (var i = 0; i < this.pendingDialogStack.length; i++) {
      if (i == this.pendingDialogStack.length - 1)
        this.overlay.style.zIndex = zIndex++;
      var dialog = this.pendingDialogStack[i];
      dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
      dialog.style.zIndex = zIndex++;
    }
  };

  dialogPolyfill.DialogManager.prototype.cancelDialog = function(event) {
    if (event.keyCode === 27 && this.pendingDialogStack.length > 0) {
      event.preventDefault();
      event.stopPropagation();
      var dialog = this.pendingDialogStack.slice(-1)[0];
      var cancelEvent;
      if (dialog) {
        if (CustomEvent) {
          cancelEvent = new CustomEvent('cancel', {
            bubbles: false
          });
        } else {
          cancelEvent = document.createEvent('HTMLEvents');
          cancelEvent.initEvent('cancel', false, true);
        }
        if (dialog.dispatchEvent(cancelEvent)) {
          dialog.close();
        }
      }
    }
  };

  dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
    if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
      throw "Too many modal dialogs";
    }

    var backdrop = document.createElement('div');
    backdrop.classList.add('backdrop');
    addEventListenerFn(backdrop, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      dialog.dispatchEvent(redirectedEvent);
    });
    dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
    dialog.dialogPolyfillInfo.backdrop = backdrop;
    this.pendingDialogStack.push(dialog);
    this.updateStacking();
  };

  dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
    var index = this.pendingDialogStack.indexOf(dialog);
    if (index == -1)
      return;
    this.pendingDialogStack.splice(index, 1);
    var backdrop = dialog.dialogPolyfillInfo.backdrop;
    backdrop.parentNode.removeChild(backdrop);
    dialog.dialogPolyfillInfo.backdrop = null;
    this.updateStacking();
  };

  addEventListenerFn(document, 'keydown', dialogPolyfill.dm.cancelDialog.bind(dialogPolyfill.dm));

  return dialogPolyfill;
})();
<commit_msg>Get window height for older IEs<commit_after>var dialogPolyfill = (function() {

  var addEventListenerFn = (window.document.addEventListener
      ? function(element, type, fn) { element.addEventListener(type, fn); }
      : function(element, type, fn) { element.attachEvent('on' + type, fn); });
  var removeEventListenerFn = (window.document.removeEventListener
      ? function(element, type, fn) { element.removeEventListener(type, fn); }
      : function(element, type, fn) { element.detachEvent('on' + type, fn); });

  var dialogPolyfill = {};

  dialogPolyfill.reposition = function(element) {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop,
		windowHeight = ('undefined' == typeof window.innerHeight) && document.body && document.body.clientHeight ?
			document.body.clientHeight :
			window.innerHeight,
    topValue = scrollTop + (windowHeight - element.offsetHeight) / 2;
    element.style.top = topValue + 'px';
    element.dialogPolyfillInfo.isTopOverridden = true;
  };

  dialogPolyfill.inNodeList = function(nodeList, node) {
    for (var i = 0; i < nodeList.length; ++i) {
      if (nodeList[i] == node)
        return true;
    }
    return false;
  };

  dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
    for (var i = 0; i < document.styleSheets.length; ++i) {
      var styleSheet = document.styleSheets[i];
      var cssRules = null;
      // Some browsers throw on cssRules.
      try {
        cssRules = styleSheet.cssRules;
      } catch (e) {}
      if (!cssRules)
        continue;
      for (var j = 0; j < cssRules.length; ++j) {
        var rule = cssRules[j];
        var selectedNodes = null;
        // Ignore errors on invalid selector texts.
        try {
          selectedNodes = document.querySelectorAll(rule.selectorText);
        } catch(e) {}
        if (!selectedNodes || !dialogPolyfill.inNodeList(selectedNodes, element))
          continue;
        var cssTop = rule.style.getPropertyValue('top');
        var cssBottom = rule.style.getPropertyValue('bottom');
        if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
          return true;
      }
    }
    return false;
  };

  dialogPolyfill.needsCentering = function(dialog) {
    var computedStyle = getComputedStyle(dialog);
    if (computedStyle.position != 'absolute')
      return false;

    // We must determine whether the top/bottom specified value is non-auto.  In
    // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
    // Firefox returns the used value. So we do this crazy thing instead: check
    // the inline style and then go through CSS rules.
    if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
        (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
      return false;
    return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
  };

  dialogPolyfill.showDialog = function(isModal) {
    if (this.open) {
      throw 'InvalidStateError: showDialog called on open dialog';
    }
    this.open = true;
    this.setAttribute('open', 'open');

    // Find element with `autofocus` attribute or first form control
    var first_form_ctrl = null;
    var autofocus = null;
    var findElementToFocus = function(root) {
      for (var i = 0; i < root.children.length; i++) {
        var elem = root.children[i];
        if (first_form_ctrl === null && !elem.disabled && (
            elem.nodeName == 'BUTTON' ||
            elem.nodeName == 'INPUT'  ||
            elem.nodeName == 'KEYGEN' ||
            elem.nodeName == 'SELECT' ||
            elem.nodeName == 'TEXTAREA')) {
          first_form_ctrl = elem;
        }
        if (elem.autofocus) {
          autofocus = elem;
          return;
        }
        findElementToFocus(elem);
        if (autofocus !== null) return;
      }
    };

    findElementToFocus(this);

    if (autofocus !== null) {
      autofocus.focus();
    } else if (first_form_ctrl !== null) {
      first_form_ctrl.focus();
    }

    if (dialogPolyfill.needsCentering(this))
      dialogPolyfill.reposition(this);
    if (isModal) {
      this.dialogPolyfillInfo.modal = true;
      dialogPolyfill.dm.pushDialog(this);
    }
  };

  dialogPolyfill.close = function(retval) {
    if (!this.open)
      throw new InvalidStateError;
    this.open = false;
    this.removeAttribute('open');

    // Leave returnValue untouched in case it was set directly on the element
    if (typeof retval != 'undefined') {
      this.returnValue = retval;
    }

    // This won't match the native <dialog> exactly because if the user sets top
    // on a centered polyfill dialog, that top gets thrown away when the dialog is
    // closed. Not sure it's possible to polyfill this perfectly.
    if (this.dialogPolyfillInfo.isTopOverridden) {
      this.style.top = 'auto';
    }

    if (this.dialogPolyfillInfo.modal) {
      dialogPolyfill.dm.removeDialog(this);
    }

    // Triggering "close" event for any attached listeners on the <dialog>
    var event;
    if (document.createEvent) {
      event = document.createEvent('HTMLEvents');
      event.initEvent('close', true, true);
    } else {
      event = new Event('close');
    }
    this.dispatchEvent(event);

    return this.returnValue;
  };

  dialogPolyfill.registerDialog = function(element) {
    if (element.show) {
      console.warn("This browser already supports <dialog>, the polyfill " +
          "may not work correctly.");
    }
    addEventListenerFn(element, 'dialog_submit', function(e) {
      element.close(e.detail.target.value);
      e.preventDefault();
      e.stopPropagation();
    });
    element.show = dialogPolyfill.showDialog.bind(element, false);
    element.showModal = dialogPolyfill.showDialog.bind(element, true);
    element.close = dialogPolyfill.close.bind(element);
    element.dialogPolyfillInfo = {};
  };

  // The overlay is used to simulate how a modal dialog blocks the document. The
  // blocking dialog is positioned on top of the overlay, and the rest of the
  // dialogs on the pending dialog stack are positioned below it. In the actual
  // implementation, the modal dialog stacking is controlled by the top layer,
  // where z-index has no effect.
  TOP_LAYER_ZINDEX = 100000;
  MAX_PENDING_DIALOGS = 100000;

  dialogPolyfill.DialogManager = function() {
    this.pendingDialogStack = [];
    this.overlay = document.createElement('div');
    this.overlay.style.width = '100%';
    this.overlay.style.height = '100%';
    this.overlay.style.position = 'fixed';
    this.overlay.style.left = '0px';
    this.overlay.style.top = '0px';
    this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

    addEventListenerFn(this.overlay, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      document.body.dispatchEvent(redirectedEvent);
    });
    addEventListenerFn(window, 'load', function() {
      var forms = document.getElementsByTagName('form');
      Array.prototype.forEach.call(forms, function(form) {
        if (form.getAttribute('method') == 'dialog') { // form.method won't return 'dialog'
          addEventListenerFn(form, 'click', function(e) {
            if (e.target.type == 'submit') {
              var event;
              if (CustomEvent) {
                event = new CustomEvent('dialog_submit', {
                  bubbles:  true,
                  detail:   { target: e.target }
                });
              } else {
                event = document.createEvent('HTMLEvents');
                event.initEvent('dialog_submit', true, true);
                event.detail = {target: e.target};
              }
              this.dispatchEvent(event);
              e.preventDefault();
            }
          });
        }
      });
    })
  };

  dialogPolyfill.dm = new dialogPolyfill.DialogManager();

  dialogPolyfill.DialogManager.prototype.blockDocument = function() {
    if (!document.body.contains(this.overlay))
      document.body.appendChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
    document.body.removeChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.updateStacking = function() {
    if (this.pendingDialogStack.length == 0) {
      this.unblockDocument();
      return;
    }
    this.blockDocument();

    var zIndex = TOP_LAYER_ZINDEX;
    for (var i = 0; i < this.pendingDialogStack.length; i++) {
      if (i == this.pendingDialogStack.length - 1)
        this.overlay.style.zIndex = zIndex++;
      var dialog = this.pendingDialogStack[i];
      dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
      dialog.style.zIndex = zIndex++;
    }
  };

  dialogPolyfill.DialogManager.prototype.cancelDialog = function(event) {
    if (event.keyCode === 27 && this.pendingDialogStack.length > 0) {
      event.preventDefault();
      event.stopPropagation();
      var dialog = this.pendingDialogStack.slice(-1)[0];
      var cancelEvent;
      if (dialog) {
        if (CustomEvent) {
          cancelEvent = new CustomEvent('cancel', {
            bubbles: false
          });
        } else {
          cancelEvent = document.createEvent('HTMLEvents');
          cancelEvent.initEvent('cancel', false, true);
        }
        if (dialog.dispatchEvent(cancelEvent)) {
          dialog.close();
        }
      }
    }
  };

  dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
    if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
      throw "Too many modal dialogs";
    }

    var backdrop = document.createElement('div');
    backdrop.classList.add('backdrop');
    addEventListenerFn(backdrop, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      dialog.dispatchEvent(redirectedEvent);
    });
    dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
    dialog.dialogPolyfillInfo.backdrop = backdrop;
    this.pendingDialogStack.push(dialog);
    this.updateStacking();
  };

  dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
    var index = this.pendingDialogStack.indexOf(dialog);
    if (index == -1)
      return;
    this.pendingDialogStack.splice(index, 1);
    var backdrop = dialog.dialogPolyfillInfo.backdrop;
    backdrop.parentNode.removeChild(backdrop);
    dialog.dialogPolyfillInfo.backdrop = null;
    this.updateStacking();
  };

  addEventListenerFn(document, 'keydown', dialogPolyfill.dm.cancelDialog.bind(dialogPolyfill.dm));

  return dialogPolyfill;
})();
<|endoftext|>


<commit_before>
window.onload = function() {

    // Page elements
    var input = document.getElementById('input');
    var openBtn = document.getElementById('open');
    var sendBtn = document.getElementById('send');
    var closeBtn = document.getElementById('close');
    var messages = document.getElementById('messages');

    // Our websocket
    var socket;

    function output(style, text){
        messages.innerHTML += "
" + text + "";
    }

    // Open
    openBtn.onclick = function(e) {
        e.preventDefault();
        if (socket !== undefined) {
            output("error", "Already connected");
            return;
        }

        socket = new WebSocket("ws://" + location.host);

        socket.onerror = function(error) {
            output("error", error);
        };

        socket.onopen = function(event) {
            output("opened", "Connected to " + event.currentTarget.url);
        };

        socket.onmessage = function(event) {
            var message = event.data;
            output("received", "<<< " + message);
        };

        socket.onclose = function(event) {
            output("closed", "Disconnected: " + event.code + " " + event.reason);
        };
    };

    // Send
    sendBtn.onclick = function(e) {
        if (socket == undefined) {
            output("error", 'Not connected');
            return;
        }
        var text = document.getElementById("input").value;
        socket.send(text);
        output("sent", ">>> " + text);
    };

    // Close
    closeBtn.onclick = function(e) {
        if (socket == undefined) {
            output('error', 'Not connected');
            return;
        }
        socket.close(1000, "Close button clicked");
        socket = undefined;
    };

};
<commit_msg>Be immune to intermediate paths, just strip off the last<commit_after>
window.onload = function() {

    // Page elements
    var input = document.getElementById('input');
    var openBtn = document.getElementById('open');
    var sendBtn = document.getElementById('send');
    var closeBtn = document.getElementById('close');
    var messages = document.getElementById('messages');

    // Our websocket
    var socket;

    function output(style, text){
        messages.innerHTML += "
" + text + "";
    }

    // Open
    openBtn.onclick = function(e) {
        e.preventDefault();
        if (socket !== undefined) {
            output("error", "Already connected");
            return;
        }

        var uri = "ws://" + location.host + location.pathname;
        uri = uri.substring(0, uri.lastIndexOf('/'));
        socket = new WebSocket(uri);

        socket.onerror = function(error) {
            output("error", error);
        };

        socket.onopen = function(event) {
            output("opened", "Connected to " + event.currentTarget.url);
        };

        socket.onmessage = function(event) {
            var message = event.data;
            output("received", "<<< " + message);
        };

        socket.onclose = function(event) {
            output("closed", "Disconnected: " + event.code + " " + event.reason);
        };
    };

    // Send
    sendBtn.onclick = function(e) {
        if (socket == undefined) {
            output("error", 'Not connected');
            return;
        }
        var text = document.getElementById("input").value;
        socket.send(text);
        output("sent", ">>> " + text);
    };

    // Close
    closeBtn.onclick = function(e) {
        if (socket == undefined) {
            output('error', 'Not connected');
            return;
        }
        socket.close(1000, "Close button clicked");
        socket = undefined;
    };

};
<|endoftext|>


<commit_before>(function (env) {
    "use strict";
    env.ddg_spice_launchbug = function(api_result){

        if (!api_result || api_result.error) {
            return Spice.failed('launchbug');
        }

        var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
        dateObj = DDG.getDateFromString(api_result.date_created),
        CreDate = [months[dateObj.getMonth()], dateObj.getDate(), dateObj.getFullYear()];

        var infoboxItems = {
            id: "Bug Id",
            can_expire: "Expires",
            information_type: "Type",
            message_count: "Comments on this Bug",
            heat: "Heat"
        };

        var infoboxData = [{
            heading: 'Bug Details'
        }];

        $.each(infoboxItems, function(key, value){
            if (api_result[key]){
                infoboxData.push({
                    label: value,
                    value: api_result[key]
                });
            }
        });

        infoboxData.push({label: "Date Created", value: CreDate.join(' ')});

        Spice.add({
            id: "launchbug",
            name: "Launchpad",
            data: api_result,
            meta: {
                sourceName: "Launchpad",
                sourceUrl: api_result.web_link
            },
            normalize: function(item) {
                return {
                    title: item.title,
                    subtitle: 'LaunchBug #' + item.id,
                    description: item.description,
                    infoboxData: infoboxData
                };
            },
            templates: {
                group: 'text',
                options: {
                    content: Spice.launchbug.content,
                    moreAt: true
                }
            }
        });
    };
}(this));

<commit_msg>Lanuchbug: Add moment.js support, create date_created using moment format<commit_after>(function (env) {
    "use strict";
    env.ddg_spice_launchbug = function(api_result){

        if (!api_result || api_result.error) {
            return Spice.failed('launchbug');
        }

        DDG.require('moment.js', function() {

            var infoboxItems = {
                id: "Bug Id",
                can_expire: "Expires",
                information_type: "Type",
                message_count: "Comments on this Bug",
                heat: "Heat",
                date_created: "Date Created"
            };

            var infoboxData = [{
                heading: 'Bug Details'
            }];

            $.each(infoboxItems, function(key, value){
                if (api_result[key]){
                    if (key === "date_created") api_result[key] = moment(api_result[key]).format("MMMM D, YYYY");
                    infoboxData.push({
                        label: value,
                        value: api_result[key]
                    });
                }
            });

            Spice.add({
                id: "launchbug",
                name: "Launchpad",
                data: api_result,
                meta: {
                    sourceName: "Launchpad",
                    sourceUrl: api_result.web_link
                },
                normalize: function(item) {
                    return {
                        title: item.title,
                        subtitle: 'LaunchBug #' + item.id,
                        description: item.description,
                        infoboxData: infoboxData
                    };
                },
                templates: {
                    group: 'text',
                    options: {
                        content: Spice.launchbug.content,
                        moreAt: true
                    }
                }
            });
        });
    };
}(this));

<|endoftext|>


<commit_before>
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: Bradley Kennedy (bk@co60.ca)
*/

/*
 * This is intended to be the location of the stored queries
 */

var StringManipulation = require('../StringManipulation');
var Client = require('../client/Client');
var ClientFilter = require('./ClientFilter');
var deepcopy = require("lodash.clonedeep");

/* Queries have the following objects:
 * name, which is the display string,
 *
 * obj which contains the query instructions
 *
 * within obj there is remote_request which is the query in JSON
 *
 * filter_revision is a boolean flag for if the query may be filtered
 * by build.revision12, if it is true we will try and find a where clause
 * in that mentions the aformentioned property, if filter_revision isn't set
 * or is false we will not remove the filter but instead not modify the query
 *
 * There is also three functions:
 * processPre(component, data) which allows you to mutate
 *   the state of the component on injestion of data, this may be left null
 *   but may be relatively useless without doing so
 * processHeaders(data) takes in a header array and returns a header array
 *   with modifications to the elements, may be null
 * processBody(data) takes in a array of arrays and returns an array of arrays,
 *   may be null.
 */

var directoryDrillDown = {
  name: 'Directory Drilldown Folders',
  obj:  {
    filter_revision: true,
    drills_down: true,
    drilldown_context: 'chrome://',
    format_headers: true,
    query_override: true,
    remote_request:{
      "from":"coverage-summary",
      "select":[
        {"aggregate":"count"},
        {"value":"source.file.total_uncovered","aggregate":"sum"},
        {"value":"source.file.total_covered","aggregate":"sum"}
      ],
      "where":{"and": [
        {"prefix":{"source.file.name":"chrome://mochikit/content/tests/SimpleTest/"}},
        {"eq":{"build.revision12":"d19d1d2136bb"}},
        {"missing":"test.url"}
      ]},
      "groupby":[{
      "name":"file",
      "value":{
        "left":[
          "source.file.name",
          {"add":[
            1,
            {
              "find":{"source.file.name":"/"},
              "start":43,
              "default":{"length":"source.file.name"}
            }
          ]}
        ]
        }
      }],
      "limit":1000
    },
    drillUp: function(drillDownContext) {
      if (!drillDownContext) {
        return this.drilldown_context;
      }
      return drillDownContext.substr(0, drillDownContext.substr(0,
            drillDownContext.length-1).lastIndexOf("/")+1);
    },
    drillDown: function(selectedRow, drillDownContext) {
      if (!drillDownContext) {
        drillDownContext = this.drilldown_context;
      }

      // This one is used if we want to remove the path
      drillDownContext += selectedRow[0].val;
      //drillDownContext = selectedRow[0].val;

      var remote_request_copy = JSON.parse(JSON.stringify(this.remote_request));
      // TODO(brad) this does NOT set the revision? DOES IT?

      ClientFilter.setProp(remote_request_copy, 'source.file.name',
          drillDownContext);
      return {
        context: drillDownContext, remote_request: remote_request_copy
      };
    },
    override: function(query, context) {
      context = context || "chrome://";

      ClientFilter.setProp(query, "start", context.length);
      ClientFilter.setProp(query, "source.file.name", context);
      return new Promise((res, rej) => {
        Client.makeRequest('activedata.allizom.org', query, (data) => {
          var colours = ["#74c274", "#f2b968", "#de6c69"];
          var levels = [0.9, 0.70, 0.0];
          var headers = [
            "Directory",
            {title: "Bar", type:"bar", colours: colours, levels: levels},
            {title: "Covered %", type:"bg", colours: colours, levels: levels},
            {title: "Covered Lines", type:"bg", colours: colours, levels: levels}
          ];

          var rows = data.data.map((row) => {
            var dir = row[0];
            dir = dir.substr(dir.substr(0, dir.length-1).lastIndexOf("/")+1);
            var cov = row[1];
            var ucov = row[2];
            var lines = cov + ucov;
            return [
              dir,
              cov/lines,
              {text: `${((cov/lines)*100).toPrecision(3)} %`, val: cov/lines},
              {text: `${cov}/${lines}`, val: cov/lines}
            ];
          });

          res({header: headers, data: rows});
        });
      });
    },
    processPre: function(comp, d) {
      comp.setState({
        data: {
          headers: d.header,
          rows: d.data
         }
      });
    },
    processHeaders: function(d) {
      return d.map(StringManipulation.header)
    },
    processBody: null,
  }
};

module.exports = {[directoryDrillDown]};
<commit_msg>Fixed bug with new query showing count as data<commit_after>
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: Bradley Kennedy (bk@co60.ca)
*/

/*
 * This is intended to be the location of the stored queries
 */

var StringManipulation = require('../StringManipulation');
var Client = require('../client/Client');
var ClientFilter = require('./ClientFilter');
var deepcopy = require("lodash.clonedeep");

/* Queries have the following objects:
 * name, which is the display string,
 *
 * obj which contains the query instructions
 *
 * within obj there is remote_request which is the query in JSON
 *
 * filter_revision is a boolean flag for if the query may be filtered
 * by build.revision12, if it is true we will try and find a where clause
 * in that mentions the aformentioned property, if filter_revision isn't set
 * or is false we will not remove the filter but instead not modify the query
 *
 * There is also three functions:
 * processPre(component, data) which allows you to mutate
 *   the state of the component on injestion of data, this may be left null
 *   but may be relatively useless without doing so
 * processHeaders(data) takes in a header array and returns a header array
 *   with modifications to the elements, may be null
 * processBody(data) takes in a array of arrays and returns an array of arrays,
 *   may be null.
 */

var directoryDrillDown = {
  name: 'Directory Drilldown Folders',
  obj:  {
    filter_revision: true,
    drills_down: true,
    drilldown_context: 'chrome://',
    format_headers: true,
    query_override: true,
    remote_request:{
      "from":"coverage-summary",
      "select":[
        {"aggregate":"count"},
        {"value":"source.file.total_uncovered","aggregate":"sum"},
        {"value":"source.file.total_covered","aggregate":"sum"}
      ],
      "where":{"and": [
        {"prefix":{"source.file.name":"chrome://mochikit/content/tests/SimpleTest/"}},
        {"eq":{"build.revision12":"d19d1d2136bb"}},
        {"missing":"test.url"}
      ]},
      "groupby":[{
      "name":"file",
      "value":{
        "left":[
          "source.file.name",
          {"add":[
            1,
            {
              "find":{"source.file.name":"/"},
              "start":43,
              "default":{"length":"source.file.name"}
            }
          ]}
        ]
        }
      }],
      "limit":1000
    },
    drillUp: function(drillDownContext) {
      if (!drillDownContext) {
        return this.drilldown_context;
      }
      return drillDownContext.substr(0, drillDownContext.substr(0,
            drillDownContext.length-1).lastIndexOf("/")+1);
    },
    drillDown: function(selectedRow, drillDownContext) {
      if (!drillDownContext) {
        drillDownContext = this.drilldown_context;
      }

      // This one is used if we want to remove the path
      drillDownContext += selectedRow[0].val;
      //drillDownContext = selectedRow[0].val;

      var remote_request_copy = JSON.parse(JSON.stringify(this.remote_request));
      // TODO(brad) this does NOT set the revision? DOES IT?

      ClientFilter.setProp(remote_request_copy, 'source.file.name',
          drillDownContext);
      return {
        context: drillDownContext, remote_request: remote_request_copy
      };
    },
    override: function(query, context) {
      context = context || "chrome://";

      ClientFilter.setProp(query, "start", context.length);
      ClientFilter.setProp(query, "source.file.name", context);
      return new Promise((res, rej) => {
        Client.makeRequest('activedata.allizom.org', query, (data) => {
          var colours = ["#74c274", "#f2b968", "#de6c69"];
          var levels = [0.9, 0.70, 0.0];
          var headers = [
            "Directory",
            {title: "Bar", type:"bar", colours: colours, levels: levels},
            {title: "Covered %", type:"bg", colours: colours, levels: levels},
            {title: "Covered Lines", type:"bg", colours: colours, levels: levels}
          ];

          var rows = data.data.map((row) => {
            var dir = row[0];
            dir = dir.substr(dir.substr(0, dir.length-1).lastIndexOf("/")+1);
            var cov = row[2];
            var ucov = row[3];
            var lines = cov + ucov;
            return [
              dir,
              cov/lines,
              {text: `${((cov/lines)*100).toPrecision(3)} %`, val: cov/lines},
              {text: `${cov}/${lines}`, val: cov/lines}
            ];
          });

          res({header: headers, data: rows});
        });
      });
    },
    processPre: function(comp, d) {
      comp.setState({
        data: {
          headers: d.header,
          rows: d.data
         }
      });
    },
    processHeaders: function(d) {
      return d.map(StringManipulation.header)
    },
    processBody: null,
  }
};

module.exports = {[directoryDrillDown]};
<|endoftext|>


<commit_before>define(["dojo/_base/kernel","dojo/_base/lang","../_base"], function(dojo,dlang,dxa){
	dojo.getObject("analytics.plugins", true, dojox);

	dojox.analytics.plugins.dojo = new (function(){
		// summary:
		//	plugin to have analyitcs return the base info dojo collects
		this.addData = dojo.hitch(dxa, "addData", "dojo");
		dojo.addOnLoad(dojo.hitch(this, function(){
			var data = {};
			for(var i in dojo){
				if ((i=="version") || ((!dojo.isObject(dojo[i]))&&(i[0]!="_"))){
					data[i]=dojo[i];
				}
			}

			if (dojo.config){data.djConfig=dojo.config}
			this.addData(data);
		}));
	})();
	return dojox.analytics.plugins.dojo;
});
<commit_msg>dojox/analytics removing references to dojox global.  refs #12863<commit_after>define(["dojo/_base/kernel","dojo/_base/lang","../_base"], function(dojo,dlang,dxa){
	var plugins = dojo.getObject("dojox.analytics.plugins", true);

	plugins.dojo = new (function(){
		// summary:
		//	plugin to have analyitcs return the base info dojo collects
		this.addData = dojo.hitch(dxa, "addData", "dojo");
		dojo.addOnLoad(dojo.hitch(this, function(){
			var data = {};
			for(var i in dojo){
				if ((i=="version") || ((!dojo.isObject(dojo[i]))&&(i[0]!="_"))){
					data[i]=dojo[i];
				}
			}

			if (dojo.config){data.djConfig=dojo.config}
			this.addData(data);
		}));
	})();
	return plugins.dojo;
});
<|endoftext|>