<!DOCTYPE html>
<!--
Copyright (C) 2015 The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>gr-date-formatter</title>

<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<script src="../../../bower_components/web-component-tester/browser.js"></script>
<script src="../../../scripts/util.js"></script>

<link rel="import" href="gr-date-formatter.html">

<test-fixture id="basic">
  <template>
    <gr-date-formatter date-str="2015-09-24 23:30:17.033000000"></gr-date-formatter>
  </template>
</test-fixture>

<script>
  suite('gr-date-formatter tests', function() {
    var element;

    /**
     * Parse server-formatter date and normalize into current timezone.
     */
    function normalizedDate(dateStr) {
      var d = util.parseDate(dateStr);
      d.setMinutes(d.getMinutes() + d.getTimezoneOffset());
      return d;
    }

    function testDates(nowStr, dateStr, expected, expectedTooltip, done) {
      // Normalize and convert the date to mimic server response.
      dateStr = normalizedDate(dateStr)
          .toJSON().replace('T', ' ').slice(0, -1);
      var clock = sinon.useFakeTimers(normalizedDate(nowStr).getTime());
      element.dateStr = dateStr;
      flush(function() {
        var span = element.$$('span');
        assert.equal(span.textContent, expected);
        assert.equal(span.title, expectedTooltip);
        clock.restore();
        done();
      });
    }

    function stubRestAPI(preferences) {
      var loggedInPromise = Promise.resolve(preferences !== null);
      var preferencesPromise = Promise.resolve(preferences);
      stub('gr-rest-api-interface', {
        getLoggedIn: sinon.stub().returns(loggedInPromise),
        getPreferences: sinon.stub().returns(preferencesPromise),
      });
      return Promise.all([loggedInPromise, preferencesPromise]);
    }

    suite('24 hours time format preference', function() {
      setup(function(done) {
        return stubRestAPI(
          {time_format: 'HHMM_24', relative_date_in_change_table: false}
        ).then(function() {
          element = fixture('basic');
          element._loadPreferences().then(function() { done(); });
        });
      });

      test('invalid dates are quietly rejected', function() {
        assert.notOk((new Date('foo')).valueOf());
        assert.equal(element._computeDateStr('foo', 'h:mm A'), '');
      });

      test('Within 24 hours on same day', function(done) {
        testDates('2015-07-29 20:34:14.985000000',
                  '2015-07-29 15:34:14.985000000',
                  '15:34', 'Jul 29, 2015, 15:34', done);
      });

      test('Within 24 hours on different days', function(done) {
        testDates('2015-07-29 03:34:14.985000000',
                  '2015-07-28 20:25:14.985000000',
                  'Jul 28', 'Jul 28, 2015, 20:25', done);
      });

      test('More than 24 hours but less than six months', function(done) {
        testDates('2015-07-29 20:34:14.985000000',
                  '2015-06-15 03:25:14.985000000',
                  'Jun 15', 'Jun 15, 2015, 3:25', done);
      });

      test('More than six months', function(done) {
        testDates('2015-09-15 20:34:00.000000000',
                  '2015-01-15 03:25:00.000000000',
                  'Jan 15, 2015', 'Jan 15, 2015, 3:25', done);
      });
    });

    suite('12 hours time format preference', function() {
      setup(function(done) {
        // relative_date_in_change_table is not set when false.
        return stubRestAPI(
          {time_format: 'HHMM_12'}
        ).then(function() {
          element = fixture('basic');
          element._loadPreferences().then(function() { done(); });
        });
      });

      test('Within 24 hours on same day', function(done) {
        testDates('2015-07-29 20:34:14.985000000',
                  '2015-07-29 15:34:14.985000000',
                  '3:34 PM', 'Jul 29, 2015, 3:34 PM', done);
      });
    });

    suite('relative date preference', function() {
      setup(function(done) {
        return stubRestAPI(
          {time_format: 'HHMM_12', relative_date_in_change_table: true}
        ).then(function() {
          element = fixture('basic');
          element._loadPreferences().then(function() { done(); });
        });
      });

      test('Within 24 hours on same day', function(done) {
        testDates('2015-07-29 20:34:14.985000000',
                  '2015-07-29 15:34:14.985000000',
                  '5 hours ago', 'Jul 29, 2015, 3:34 PM', done);
      });

      test('More than six months', function(done) {
        testDates('2015-09-15 20:34:00.000000000',
                  '2015-01-15 03:25:00.000000000',
                  '8 months ago', 'Jan 15, 2015, 3:25 AM', done);
      });
    });

    suite('logged in', function() {
      setup(function(done) {
        return stubRestAPI(
          {time_format: 'HHMM_12', relative_date_in_change_table: true}
        ).then(function() {
          element = fixture('basic');
          element._loadPreferences().then(function() { done(); });
        });
      });

      test('Preferences are respected', function() {
        assert.equal(element._timeFormat, 'h:mm A');
        assert.isTrue(element._relative);
      });
    });

    suite('logged out', function() {
      setup(function(done) {
        return stubRestAPI(null).then(function() {
          element = fixture('basic');
          element._loadPreferences().then(function() { done(); });
        });
      });

      test('Default preferences are respected', function() {
        assert.equal(element._timeFormat, 'H:mm');
        assert.isFalse(element._relative);
      });
    });
  });
</script>
