github.com/zoomfoo/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/ui/tests/integration/job-page/service-test.js (about)

     1  import { getOwner } from '@ember/application';
     2  import { assign } from '@ember/polyfills';
     3  import { test, moduleForComponent } from 'ember-qunit';
     4  import { click, find } from 'ember-native-dom-helpers';
     5  import wait from 'ember-test-helpers/wait';
     6  import hbs from 'htmlbars-inline-precompile';
     7  import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
     8  import { startJob, stopJob, expectError, expectDeleteRequest, expectStartRequest } from './helpers';
     9  import Job from 'nomad-ui/tests/pages/jobs/detail';
    10  import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
    11  
    12  moduleForComponent('job-page/service', 'Integration | Component | job-page/service', {
    13    integration: true,
    14    beforeEach() {
    15      Job.setContext(this);
    16      fragmentSerializerInitializer(getOwner(this));
    17      window.localStorage.clear();
    18      this.store = getOwner(this).lookup('service:store');
    19      this.server = startMirage();
    20      this.server.create('namespace');
    21    },
    22    afterEach() {
    23      Job.removeContext();
    24      this.server.shutdown();
    25      window.localStorage.clear();
    26    },
    27  });
    28  
    29  const commonTemplate = hbs`
    30    {{job-page/service
    31      job=job
    32      sortProperty=sortProperty
    33      sortDescending=sortDescending
    34      currentPage=currentPage
    35      gotoJob=gotoJob}}
    36  `;
    37  
    38  const commonProperties = job => ({
    39    job,
    40    sortProperty: 'name',
    41    sortDescending: true,
    42    currentPage: 1,
    43    gotoJob() {},
    44  });
    45  
    46  const makeMirageJob = (server, props = {}) =>
    47    server.create(
    48      'job',
    49      assign(
    50        {
    51          type: 'service',
    52          createAllocations: false,
    53          status: 'running',
    54        },
    55        props
    56      )
    57    );
    58  
    59  test('Stopping a job sends a delete request for the job', function(assert) {
    60    let job;
    61  
    62    const mirageJob = makeMirageJob(this.server);
    63    this.store.findAll('job');
    64  
    65    return wait()
    66      .then(() => {
    67        job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
    68  
    69        this.setProperties(commonProperties(job));
    70        this.render(commonTemplate);
    71  
    72        return wait();
    73      })
    74      .then(stopJob)
    75      .then(() => expectDeleteRequest(assert, this.server, job));
    76  });
    77  
    78  test('Stopping a job without proper permissions shows an error message', function(assert) {
    79    this.server.pretender.delete('/v1/job/:id', () => [403, {}, null]);
    80  
    81    const mirageJob = makeMirageJob(this.server);
    82    this.store.findAll('job');
    83  
    84    return wait()
    85      .then(() => {
    86        const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
    87  
    88        this.setProperties(commonProperties(job));
    89        this.render(commonTemplate);
    90  
    91        return wait();
    92      })
    93      .then(stopJob)
    94      .then(expectError(assert, 'Could Not Stop Job'));
    95  });
    96  
    97  test('Starting a job sends a post request for the job using the current definition', function(assert) {
    98    let job;
    99  
   100    const mirageJob = makeMirageJob(this.server, { status: 'dead' });
   101    this.store.findAll('job');
   102  
   103    return wait()
   104      .then(() => {
   105        job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   106  
   107        this.setProperties(commonProperties(job));
   108        this.render(commonTemplate);
   109  
   110        return wait();
   111      })
   112      .then(startJob)
   113      .then(() => expectStartRequest(assert, this.server, job));
   114  });
   115  
   116  test('Starting a job without proper permissions shows an error message', function(assert) {
   117    this.server.pretender.post('/v1/job/:id', () => [403, {}, null]);
   118  
   119    const mirageJob = makeMirageJob(this.server, { status: 'dead' });
   120    this.store.findAll('job');
   121  
   122    return wait()
   123      .then(() => {
   124        const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   125  
   126        this.setProperties(commonProperties(job));
   127        this.render(commonTemplate);
   128  
   129        return wait();
   130      })
   131      .then(startJob)
   132      .then(expectError(assert, 'Could Not Start Job'));
   133  });
   134  
   135  test('Recent allocations shows allocations in the job context', function(assert) {
   136    let job;
   137  
   138    this.server.create('node');
   139    const mirageJob = makeMirageJob(this.server, { createAllocations: true });
   140    this.store.findAll('job');
   141  
   142    return wait()
   143      .then(() => {
   144        job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   145  
   146        this.setProperties(commonProperties(job));
   147        this.render(commonTemplate);
   148  
   149        return wait();
   150      })
   151      .then(() => {
   152        const allocation = this.server.db.allocations.sortBy('modifyIndex').reverse()[0];
   153        const allocationRow = Job.allocations.objectAt(0);
   154  
   155        assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'ID');
   156        assert.equal(allocationRow.taskGroup, allocation.taskGroup, 'Task Group name');
   157      });
   158  });
   159  
   160  test('Recent allocations caps out at five', function(assert) {
   161    let job;
   162  
   163    this.server.create('node');
   164    const mirageJob = makeMirageJob(this.server);
   165    this.server.createList('allocation', 10);
   166  
   167    this.store.findAll('job');
   168  
   169    return wait().then(() => {
   170      job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   171  
   172      this.setProperties(commonProperties(job));
   173      this.render(commonTemplate);
   174  
   175      return wait().then(() => {
   176        assert.equal(Job.allocations.length, 5, 'Capped at 5 allocations');
   177        assert.ok(
   178          Job.viewAllAllocations.includes(job.get('allocations.length') + ''),
   179          `View link mentions ${job.get('allocations.length')} allocations`
   180        );
   181      });
   182    });
   183  });
   184  
   185  test('Recent allocations shows an empty message when the job has no allocations', function(assert) {
   186    let job;
   187  
   188    this.server.create('node');
   189    const mirageJob = makeMirageJob(this.server);
   190  
   191    this.store.findAll('job');
   192  
   193    return wait()
   194      .then(() => {
   195        job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   196  
   197        this.setProperties(commonProperties(job));
   198        this.render(commonTemplate);
   199  
   200        return wait();
   201      })
   202      .then(() => {
   203        assert.ok(
   204          Job.recentAllocationsEmptyState.headline.includes('No Allocations'),
   205          'No allocations empty message'
   206        );
   207      });
   208  });
   209  
   210  test('Active deployment can be promoted', function(assert) {
   211    let job;
   212    let deployment;
   213  
   214    this.server.create('node');
   215    const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
   216  
   217    this.store.findAll('job');
   218  
   219    return wait()
   220      .then(() => {
   221        job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   222        deployment = job.get('latestDeployment');
   223  
   224        this.setProperties(commonProperties(job));
   225        this.render(commonTemplate);
   226  
   227        return wait();
   228      })
   229      .then(() => {
   230        click('[data-test-promote-canary]');
   231        return wait();
   232      })
   233      .then(() => {
   234        const requests = this.server.pretender.handledRequests;
   235        assert.ok(
   236          requests
   237            .filterBy('method', 'POST')
   238            .findBy('url', `/v1/deployment/promote/${deployment.get('id')}`),
   239          'A promote POST request was made'
   240        );
   241      });
   242  });
   243  
   244  test('When promoting the active deployment fails, an error is shown', function(assert) {
   245    this.server.pretender.post('/v1/deployment/promote/:id', () => [403, {}, null]);
   246  
   247    let job;
   248  
   249    this.server.create('node');
   250    const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
   251  
   252    this.store.findAll('job');
   253  
   254    return wait()
   255      .then(() => {
   256        job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
   257  
   258        this.setProperties(commonProperties(job));
   259        this.render(commonTemplate);
   260  
   261        return wait();
   262      })
   263      .then(() => {
   264        click('[data-test-promote-canary]');
   265        return wait();
   266      })
   267      .then(() => {
   268        assert.equal(
   269          find('[data-test-job-error-title]').textContent,
   270          'Could Not Promote Deployment',
   271          'Appropriate error is shown'
   272        );
   273        assert.ok(
   274          find('[data-test-job-error-body]').textContent.includes('ACL'),
   275          'The error message mentions ACLs'
   276        );
   277  
   278        click('[data-test-job-error-close]');
   279        assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable');
   280        return wait();
   281      });
   282  });