+
- {{#if this.namespaceOptions.length}}
-
+ {{#if this.system.shouldShowNamespaces}}
+
{{/if}}
diff --git a/ui/tests/acceptance/job-run-test.js b/ui/tests/acceptance/job-run-test.js
index a7bcea9231d..0487266f346 100644
--- a/ui/tests/acceptance/job-run-test.js
+++ b/ui/tests/acceptance/job-run-test.js
@@ -1,3 +1,4 @@
+import AdapterError from '@ember-data/adapter/error';
import {
click,
currentRouteName,
@@ -6,6 +7,10 @@ import {
} from '@ember/test-helpers';
import { assign } from '@ember/polyfills';
import { module, test } from 'qunit';
+import {
+ selectChoose,
+ clickTrigger,
+} from 'ember-power-select/test-support/helpers';
import { setupApplicationTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
@@ -310,5 +315,111 @@ module('Acceptance | job run', function (hooks) {
.dom('[data-test-template-card=foo]')
.exists('The newly created template appears in the list.');
});
+
+ test('a toast notification alerts the user if there is an error saving the newly created job template', async function (assert) {
+ assert.expect(5);
+ // Arrange
+ await JobRun.visit();
+ await click('[data-test-choose-template]');
+
+ // Assert
+ assert
+ .dom('[data-test-empty-templates-list-headline]')
+ .exists('No templates are listed if none have been created.');
+
+ await click('[data-test-create-inline]');
+ assert.equal(currentRouteName(), 'jobs.run.templates.new');
+ assert
+ .dom('[data-test-save-template]')
+ .isDisabled('the save button should be disabled if no path is set');
+
+ await fillIn('[data-test-template-name]', 'try@');
+ await fillIn('[data-test-template-description]', 'foo-bar-baz');
+ const codeMirror = getCodeMirrorInstance('[data-test-template-json]');
+ codeMirror.setValue(jsonJob());
+
+ server.put('/var/:varId?cas=0', function () {
+ return new AdapterError({
+ detail: `invalid path "nomad/job-templates/try@"`,
+ status: 500,
+ });
+ });
+
+ await click('[data-test-save-template]');
+ assert.equal(
+ currentRouteName(),
+ 'jobs.run.templates.new',
+ 'We do not navigate away from the page if an error is returned by the API.'
+ );
+ assert
+ .dom('.flash-message.alert-error')
+ .exists('A toast error message pops up.');
+ });
+
+ test('a user cannot create a job template if one with the same name and namespace already exists', async function (assert) {
+ assert.expect(4);
+ // Arrange
+ await JobRun.visit();
+ await click('[data-test-choose-template]');
+ server.create('variable', {
+ path: 'nomad/job-templates/foo',
+ namespace: 'default',
+ id: 'nomad/job-templates/foo',
+ });
+ server.create('namespace', { id: 'test' });
+
+ // Assert
+ assert
+ .dom('[data-test-empty-templates-list-headline]')
+ .exists('No templates are listed if none have been created.');
+
+ await click('[data-test-create-inline]');
+ assert.equal(currentRouteName(), 'jobs.run.templates.new');
+
+ await fillIn('[data-test-template-name]', 'foo');
+ assert
+ .dom('[data-test-duplicate-error]')
+ .exists('an error message alerts the user');
+
+ await clickTrigger('[data-test-namespace-facet]');
+ await selectChoose('[data-test-namespace-facet]', 'test');
+
+ assert
+ .dom('[data-test-duplicate-error]')
+ .doesNotExist(
+ 'an error disappears when name or namespace combination is unique'
+ );
+ });
+
+ test('a user can save code from the editor as a template', async function (assert) {
+ assert.expect(4);
+ // Arrange
+ await JobRun.visit();
+ await JobRun.editor.editor.fillIn(jsonJob());
+
+ await click('[data-test-save-as-template]');
+ assert.equal(
+ currentRouteName(),
+ 'jobs.run.templates.new',
+ 'We navigate template creation page.'
+ );
+
+ // Assert
+ assert
+ .dom('[data-test-template-name]')
+ .hasNoText('No template name is prefilled.');
+ assert
+ .dom('[data-test-template-description]')
+ .hasNoText('No template description is prefilled.');
+
+ const codeMirror = getCodeMirrorInstance('[data-test-template-json]');
+ const json = codeMirror.getValue();
+
+ assert.equal(
+ json,
+ jsonJob(),
+ 'Template is filled out with text from the editor.'
+ );
+ });
});
});