<!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, 03: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, 03: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, 'HH:mm');
        assert.isFalse(element._relative);
      });
    });
  });
</script>
