github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/tests/unit/components/stats-time-series-test.js (about)

     1  import { module, test } from 'qunit';
     2  import { setupTest } from 'ember-qunit';
     3  import moment from 'moment';
     4  import d3Format from 'd3-format';
     5  import d3TimeFormat from 'd3-time-format';
     6  import setupGlimmerComponentFactory from 'nomad-ui/tests/helpers/glimmer-factory';
     7  
     8  module('Unit | Component | stats-time-series', function (hooks) {
     9    setupTest(hooks);
    10    setupGlimmerComponentFactory(hooks, 'stats-time-series');
    11  
    12    const ts = (offset, resolution = 'm') =>
    13      moment().subtract(offset, resolution).toDate();
    14  
    15    const wideData = [
    16      { timestamp: ts(20), percent: 0.5 },
    17      { timestamp: ts(18), percent: 0.5 },
    18      { timestamp: ts(16), percent: 0.4 },
    19      { timestamp: ts(14), percent: 0.3 },
    20      { timestamp: ts(12), percent: 0.9 },
    21      { timestamp: ts(10), percent: 0.3 },
    22      { timestamp: ts(8), percent: 0.3 },
    23      { timestamp: ts(6), percent: 0.4 },
    24      { timestamp: ts(4), percent: 0.5 },
    25      { timestamp: ts(2), percent: 0.6 },
    26      { timestamp: ts(0), percent: 0.6 },
    27    ];
    28  
    29    const narrowData = [
    30      { timestamp: ts(20, 's'), percent: 0.5 },
    31      { timestamp: ts(18, 's'), percent: 0.5 },
    32      { timestamp: ts(16, 's'), percent: 0.4 },
    33      { timestamp: ts(14, 's'), percent: 0.3 },
    34      { timestamp: ts(12, 's'), percent: 0.9 },
    35      { timestamp: ts(10, 's'), percent: 0.3 },
    36    ];
    37  
    38    const unboundedData = [
    39      { timestamp: ts(20, 's'), percent: -0.5 },
    40      { timestamp: ts(18, 's'), percent: 1.5 },
    41    ];
    42  
    43    const nullData = [
    44      { timestamp: ts(20, 's'), percent: null },
    45      { timestamp: ts(18, 's'), percent: null },
    46    ];
    47  
    48    test('xFormat is time-formatted for hours, minutes, and seconds', function (assert) {
    49      assert.expect(11);
    50  
    51      const chart = this.createComponent({ data: wideData });
    52  
    53      wideData.forEach((datum) => {
    54        assert.equal(
    55          chart.xFormat(datum.timestamp),
    56          d3TimeFormat.timeFormat('%H:%M:%S')(datum.timestamp)
    57        );
    58      });
    59    });
    60  
    61    test('yFormat is percent-formatted', function (assert) {
    62      assert.expect(11);
    63  
    64      const chart = this.createComponent({ data: wideData });
    65  
    66      wideData.forEach((datum) => {
    67        assert.equal(
    68          chart.yFormat(datum.percent),
    69          d3Format.format('.1~%')(datum.percent)
    70        );
    71      });
    72    });
    73  
    74    test('x scale domain is at least five minutes', function (assert) {
    75      const chart = this.createComponent({ data: narrowData });
    76  
    77      assert.equal(
    78        +chart.xScale(narrowData, 0).domain()[0],
    79        +moment(Math.max(...narrowData.mapBy('timestamp')))
    80          .subtract(5, 'm')
    81          .toDate(),
    82        'The lower bound of the xScale is 5 minutes ago'
    83      );
    84    });
    85  
    86    test('x scale domain is greater than five minutes when the domain of the data is larger than five minutes', function (assert) {
    87      const chart = this.createComponent({ data: wideData });
    88  
    89      assert.equal(
    90        +chart.xScale(wideData, 0).domain()[0],
    91        Math.min(...wideData.mapBy('timestamp')),
    92        'The lower bound of the xScale is the oldest timestamp in the dataset'
    93      );
    94    });
    95  
    96    test('y scale domain is typically 0 to 1 (0 to 100%)', function (assert) {
    97      const chart = this.createComponent({ data: wideData });
    98  
    99      assert.deepEqual(
   100        [
   101          Math.min(...wideData.mapBy('percent')),
   102          Math.max(...wideData.mapBy('percent')),
   103        ],
   104        [0.3, 0.9],
   105        'The bounds of the value prop of the dataset is narrower than 0 - 1'
   106      );
   107  
   108      assert.deepEqual(
   109        chart.yScale(wideData, 0).domain(),
   110        [0, 1],
   111        'The bounds of the yScale are still 0 and 1'
   112      );
   113    });
   114  
   115    test('the extent of the y domain overrides the default 0 to 1 domain when there are values beyond these bounds', function (assert) {
   116      const chart = this.createComponent({ data: unboundedData });
   117  
   118      assert.deepEqual(
   119        chart.yScale(unboundedData, 0).domain(),
   120        [-0.5, 1.5],
   121        'The bounds of the yScale match the bounds of the unbounded data'
   122      );
   123  
   124      chart.args.data = [unboundedData[0]];
   125  
   126      assert.deepEqual(
   127        chart.yScale(chart.args.data, 0).domain(),
   128        [-0.5, 1],
   129        'The upper bound is still the default 1, but the lower bound is overridden due to the unbounded low value'
   130      );
   131  
   132      chart.args.data = [unboundedData[1]];
   133  
   134      assert.deepEqual(
   135        chart.yScale(chart.args.data, 0).domain(),
   136        [0, 1.5],
   137        'The lower bound is still the default 0, but the upper bound is overridden due to the unbounded high value'
   138      );
   139    });
   140  
   141    test('when there are only empty frames in the data array, the default y domain is used', function (assert) {
   142      const chart = this.createComponent({ data: nullData });
   143  
   144      assert.deepEqual(
   145        chart.yScale(nullData, 0).domain(),
   146        [0, 1],
   147        'The bounds are 0 and 1'
   148      );
   149    });
   150  });