github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/tests/unit/adapters/node-test.js (about)

     1  import { run } from '@ember/runloop';
     2  import { module, test } from 'qunit';
     3  import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
     4  import { setupTest } from 'ember-qunit';
     5  import { settled } from '@ember/test-helpers';
     6  
     7  module('Unit | Adapter | Node', function (hooks) {
     8    setupTest(hooks);
     9  
    10    hooks.beforeEach(function () {
    11      this.store = this.owner.lookup('service:store');
    12      this.subject = () => this.store.adapterFor('node');
    13  
    14      window.localStorage.clear();
    15  
    16      this.server = startMirage();
    17  
    18      this.server.create('region', { id: 'region-1' });
    19      this.server.create('region', { id: 'region-2' });
    20  
    21      this.server.create('node', { id: 'node-1' });
    22      this.server.create('node', { id: 'node-2' });
    23      this.server.create('job', { id: 'job-1', createAllocations: false });
    24  
    25      this.server.create('allocation', { id: 'node-1-1', nodeId: 'node-1' });
    26      this.server.create('allocation', { id: 'node-1-2', nodeId: 'node-1' });
    27      this.server.create('allocation', { id: 'node-2-1', nodeId: 'node-2' });
    28      this.server.create('allocation', { id: 'node-2-2', nodeId: 'node-2' });
    29    });
    30  
    31    hooks.afterEach(function () {
    32      this.server.shutdown();
    33    });
    34  
    35    test('findHasMany removes old related models from the store', async function (assert) {
    36      // Fetch the model and related allocations
    37      let node = await run(() => this.store.findRecord('node', 'node-1'));
    38      let allocations = await run(() => findHasMany(node, 'allocations'));
    39      assert.equal(
    40        allocations.get('length'),
    41        this.server.db.allocations.where({ nodeId: node.get('id') }).length,
    42        'Allocations returned from the findHasMany matches the db state'
    43      );
    44  
    45      await settled();
    46      server.db.allocations.remove('node-1-1');
    47  
    48      allocations = await run(() => findHasMany(node, 'allocations'));
    49      const dbAllocations = this.server.db.allocations.where({
    50        nodeId: node.get('id'),
    51      });
    52      assert.equal(
    53        allocations.get('length'),
    54        dbAllocations.length,
    55        'Allocations returned from the findHasMany matches the db state'
    56      );
    57      assert.equal(
    58        this.store.peekAll('allocation').get('length'),
    59        dbAllocations.length,
    60        'Server-side deleted allocation was removed from the store'
    61      );
    62    });
    63  
    64    test('findHasMany does not remove old unrelated models from the store', async function (assert) {
    65      // Fetch the first node and related allocations
    66      const node = await run(() => this.store.findRecord('node', 'node-1'));
    67      await run(() => findHasMany(node, 'allocations'));
    68  
    69      // Also fetch the second node and related allocations;
    70      const node2 = await run(() => this.store.findRecord('node', 'node-2'));
    71      await run(() => findHasMany(node2, 'allocations'));
    72  
    73      await settled();
    74      assert.deepEqual(
    75        this.store.peekAll('allocation').mapBy('id').sort(),
    76        ['node-1-1', 'node-1-2', 'node-2-1', 'node-2-2'],
    77        'All allocations for the first and second node are in the store'
    78      );
    79  
    80      server.db.allocations.remove('node-1-1');
    81  
    82      // Reload the related allocations now that one was removed server-side
    83      await run(() => findHasMany(node, 'allocations'));
    84      assert.deepEqual(
    85        this.store.peekAll('allocation').mapBy('id').sort(),
    86        ['node-1-2', 'node-2-1', 'node-2-2'],
    87        'The deleted allocation is removed from the store and the allocations associated with the other node are untouched'
    88      );
    89    });
    90  
    91    const testCases = [
    92      {
    93        variation: '',
    94        id: 'node-1',
    95        region: null,
    96        eligibility: 'POST /v1/node/node-1/eligibility',
    97        drain: 'POST /v1/node/node-1/drain',
    98      },
    99      {
   100        variation: 'with non-default region',
   101        id: 'node-1',
   102        region: 'region-2',
   103        eligibility: 'POST /v1/node/node-1/eligibility?region=region-2',
   104        drain: 'POST /v1/node/node-1/drain?region=region-2',
   105      },
   106    ];
   107  
   108    testCases.forEach((testCase) => {
   109      test(`setEligible makes the correct POST request to /:node_id/eligibility ${testCase.variation}`, async function (assert) {
   110        const { pretender } = this.server;
   111        if (testCase.region)
   112          window.localStorage.nomadActiveRegion = testCase.region;
   113  
   114        const node = await run(() => this.store.findRecord('node', testCase.id));
   115        await this.subject().setEligible(node);
   116  
   117        const request = pretender.handledRequests.lastObject;
   118        assert.equal(`${request.method} ${request.url}`, testCase.eligibility);
   119        assert.deepEqual(JSON.parse(request.requestBody), {
   120          NodeID: node.id,
   121          Eligibility: 'eligible',
   122        });
   123      });
   124  
   125      test(`setIneligible makes the correct POST request to /:node_id/eligibility ${testCase.variation}`, async function (assert) {
   126        const { pretender } = this.server;
   127        if (testCase.region)
   128          window.localStorage.nomadActiveRegion = testCase.region;
   129  
   130        const node = await run(() => this.store.findRecord('node', testCase.id));
   131        await this.subject().setIneligible(node);
   132  
   133        const request = pretender.handledRequests.lastObject;
   134        assert.equal(`${request.method} ${request.url}`, testCase.eligibility);
   135        assert.deepEqual(JSON.parse(request.requestBody), {
   136          NodeID: node.id,
   137          Eligibility: 'ineligible',
   138        });
   139      });
   140  
   141      test(`drain makes the correct POST request to /:node_id/drain with appropriate defaults ${testCase.variation}`, async function (assert) {
   142        const { pretender } = this.server;
   143        if (testCase.region)
   144          window.localStorage.nomadActiveRegion = testCase.region;
   145  
   146        const node = await run(() => this.store.findRecord('node', testCase.id));
   147        await this.subject().drain(node);
   148  
   149        const request = pretender.handledRequests.lastObject;
   150        assert.equal(`${request.method} ${request.url}`, testCase.drain);
   151        assert.deepEqual(JSON.parse(request.requestBody), {
   152          NodeID: node.id,
   153          DrainSpec: {
   154            Deadline: 0,
   155            IgnoreSystemJobs: true,
   156          },
   157        });
   158      });
   159  
   160      test(`drain makes the correct POST request to /:node_id/drain with the provided drain spec ${testCase.variation}`, async function (assert) {
   161        const { pretender } = this.server;
   162        if (testCase.region)
   163          window.localStorage.nomadActiveRegion = testCase.region;
   164  
   165        const node = await run(() => this.store.findRecord('node', testCase.id));
   166  
   167        const spec = { Deadline: 123456789, IgnoreSystemJobs: false };
   168        await this.subject().drain(node, spec);
   169  
   170        const request = pretender.handledRequests.lastObject;
   171        assert.equal(`${request.method} ${request.url}`, testCase.drain);
   172        assert.deepEqual(JSON.parse(request.requestBody), {
   173          NodeID: node.id,
   174          DrainSpec: {
   175            Deadline: spec.Deadline,
   176            IgnoreSystemJobs: spec.IgnoreSystemJobs,
   177          },
   178        });
   179      });
   180  
   181      test(`forceDrain makes the correct POST request to /:node_id/drain with appropriate defaults ${testCase.variation}`, async function (assert) {
   182        const { pretender } = this.server;
   183        if (testCase.region)
   184          window.localStorage.nomadActiveRegion = testCase.region;
   185  
   186        const node = await run(() => this.store.findRecord('node', testCase.id));
   187  
   188        await this.subject().forceDrain(node);
   189  
   190        const request = pretender.handledRequests.lastObject;
   191        assert.equal(`${request.method} ${request.url}`, testCase.drain);
   192        assert.deepEqual(JSON.parse(request.requestBody), {
   193          NodeID: node.id,
   194          DrainSpec: {
   195            Deadline: -1,
   196            IgnoreSystemJobs: true,
   197          },
   198        });
   199      });
   200  
   201      test(`forceDrain makes the correct POST request to /:node_id/drain with the provided drain spec ${testCase.variation}`, async function (assert) {
   202        const { pretender } = this.server;
   203        if (testCase.region)
   204          window.localStorage.nomadActiveRegion = testCase.region;
   205  
   206        const node = await run(() => this.store.findRecord('node', testCase.id));
   207  
   208        const spec = { Deadline: 123456789, IgnoreSystemJobs: false };
   209        await this.subject().forceDrain(node, spec);
   210  
   211        const request = pretender.handledRequests.lastObject;
   212        assert.equal(`${request.method} ${request.url}`, testCase.drain);
   213        assert.deepEqual(JSON.parse(request.requestBody), {
   214          NodeID: node.id,
   215          DrainSpec: {
   216            Deadline: -1,
   217            IgnoreSystemJobs: spec.IgnoreSystemJobs,
   218          },
   219        });
   220      });
   221  
   222      test(`cancelDrain makes the correct POST request to /:node_id/drain ${testCase.variation}`, async function (assert) {
   223        const { pretender } = this.server;
   224        if (testCase.region)
   225          window.localStorage.nomadActiveRegion = testCase.region;
   226  
   227        const node = await run(() => this.store.findRecord('node', testCase.id));
   228  
   229        await this.subject().cancelDrain(node);
   230  
   231        const request = pretender.handledRequests.lastObject;
   232        assert.equal(`${request.method} ${request.url}`, testCase.drain);
   233        assert.deepEqual(JSON.parse(request.requestBody), {
   234          NodeID: node.id,
   235          DrainSpec: null,
   236        });
   237      });
   238    });
   239  });
   240  
   241  // Using fetchLink on a model's hasMany relationship exercises the adapter's
   242  // findHasMany method as well normalizing the response and pushing it to the store
   243  function findHasMany(model, relationshipName) {
   244    const relationship = model.relationshipFor(relationshipName);
   245    return model.hasMany(relationship.key).reload();
   246  }