mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-23 07:31:09 +02:00
* namespace and ui-config, running out of time ahhh * fix some tests * triple back to back runs on namespace and we're solid * add cleanup test pollution on config-ui/messages and also remove the empty state check as we do that in the component test: * Fix test error: "Promise rejected during "it should show the list of custom messages": _generalSelectors.GENERAL.listItem is not a function" * fix more tests --------- Co-authored-by: Shannon Roberts <shannon.roberts@hashicorp.com>
198 lines
7.1 KiB
JavaScript
198 lines
7.1 KiB
JavaScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import { module, test } from 'qunit';
|
|
import { setupRenderingTest } from 'ember-qunit';
|
|
import { render, fillIn, findAll, click, find } from '@ember/test-helpers';
|
|
import sinon from 'sinon';
|
|
import hbs from 'htmlbars-inline-precompile';
|
|
import Service from '@ember/service';
|
|
import { GENERAL } from 'vault/tests/helpers/general-selectors';
|
|
|
|
class AuthService extends Service {
|
|
authData = { userRootNamespace: '' };
|
|
}
|
|
|
|
class NamespaceService extends Service {
|
|
accessibleNamespaces = ['parent1', 'parent1/child1'];
|
|
path = 'parent1/child1';
|
|
|
|
findNamespacesForUser = {
|
|
perform: () => Promise.resolve(),
|
|
};
|
|
}
|
|
|
|
class StoreService extends Service {
|
|
findRecord(modelType, id) {
|
|
return new Promise((resolve, reject) => {
|
|
if (modelType === 'capabilities' && id === 'sys/namespaces/') {
|
|
resolve(); // Simulate a successful response
|
|
} else {
|
|
reject({ httpStatus: 404, message: 'not found' }); // Simulate an error response
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function getMockCapabilitiesModel(canList) {
|
|
// Mock for the Capabilities model
|
|
return {
|
|
path: 'sys/namespaces/',
|
|
capabilities: canList ? ['list'] : [],
|
|
get(property) {
|
|
if (property === 'canList') {
|
|
return this.capabilities.includes('list');
|
|
}
|
|
return undefined;
|
|
},
|
|
};
|
|
}
|
|
|
|
const INITIALIZED_NAMESPACES = ['root', 'parent1', 'parent1/child1'];
|
|
|
|
module('Integration | Component | namespace-picker', function (hooks) {
|
|
setupRenderingTest(hooks);
|
|
|
|
hooks.beforeEach(function () {
|
|
this.owner.register('service:auth', AuthService);
|
|
this.owner.register('service:namespace', NamespaceService);
|
|
this.owner.register('service:store', StoreService);
|
|
});
|
|
|
|
test('it focuses the search input field when the component is loaded', async function (assert) {
|
|
await render(hbs`<NamespacePicker />`);
|
|
await click(GENERAL.toggleInput('namespace-picker'));
|
|
|
|
// Verify that the search input field is focused
|
|
const searchInput = find(GENERAL.inputByAttr('Search namespaces'));
|
|
assert.strictEqual(
|
|
document.activeElement,
|
|
searchInput,
|
|
'The search input field is focused on component load'
|
|
);
|
|
});
|
|
|
|
test('it filters namespace options based on search input', async function (assert) {
|
|
await render(hbs`<NamespacePicker/>`);
|
|
await click(GENERAL.toggleInput('namespace-picker'));
|
|
|
|
// Verify all namespaces are displayed initially which are pre-populated in the NamespaceService
|
|
for (const namespace of INITIALIZED_NAMESPACES) {
|
|
assert.dom(GENERAL.button(namespace)).exists(`Namespace "${namespace}" is displayed initially`);
|
|
}
|
|
// Simulate typing into the search input
|
|
await fillIn(GENERAL.inputByAttr('Search namespaces'), 'child1');
|
|
|
|
// Verify that only namespaces matching the search input are displayed
|
|
assert.strictEqual(
|
|
findAll(GENERAL.inputByAttr('Search namespaces')).length,
|
|
1,
|
|
'Only matching namespaces are displayed after filtering'
|
|
);
|
|
|
|
// Clear the search input
|
|
await fillIn(GENERAL.inputByAttr('Search namespaces'), '');
|
|
|
|
// Verify all namespaces are displayed after clearing the search input
|
|
assert.strictEqual(
|
|
findAll(GENERAL.button()).length,
|
|
3,
|
|
'All namespaces are displayed after clearing the search input'
|
|
);
|
|
});
|
|
|
|
test('it shows both "Manage" and "Refresh list" action buttons when canList is true', async function (assert) {
|
|
const storeStub = this.owner.lookup('service:store');
|
|
sinon.stub(storeStub, 'findRecord').callsFake((modelType, id) => {
|
|
if (modelType === 'capabilities' && id === 'sys/namespaces/') {
|
|
return Promise.resolve(getMockCapabilitiesModel(true));
|
|
}
|
|
return Promise.reject();
|
|
});
|
|
|
|
await render(hbs`<NamespacePicker />`);
|
|
await click(GENERAL.toggleInput('namespace-picker'));
|
|
|
|
// Verify that the "Refresh List" button is visible
|
|
assert.dom(GENERAL.button('Refresh list')).exists('Refresh List button is visible');
|
|
assert.dom(GENERAL.button('Manage')).exists('Manage button is visible');
|
|
});
|
|
|
|
test('it hides the refresh button when canList is false', async function (assert) {
|
|
const storeStub = this.owner.lookup('service:store');
|
|
sinon.stub(storeStub, 'findRecord').callsFake((modelType, id) => {
|
|
if (modelType === 'capabilities' && id === 'sys/namespaces/') {
|
|
return Promise.resolve(getMockCapabilitiesModel(false));
|
|
}
|
|
return Promise.reject();
|
|
});
|
|
|
|
await render(hbs`<NamespacePicker />`);
|
|
await click(GENERAL.toggleInput('namespace-picker'));
|
|
|
|
// Verify that the buttons are hidden
|
|
assert.dom(GENERAL.button('Refresh list')).doesNotExist('Refresh List button is hidden');
|
|
assert.dom(GENERAL.button('Manage')).exists('Manage button is hidden');
|
|
});
|
|
|
|
test('it hides both action buttons when the capabilities store throws an error', async function (assert) {
|
|
const storeStub = this.owner.lookup('service:store');
|
|
sinon.stub(storeStub, 'findRecord').callsFake(() => {
|
|
return Promise.reject();
|
|
});
|
|
|
|
await render(hbs`<NamespacePicker />`);
|
|
await click(GENERAL.toggleInput('namespace-picker'));
|
|
|
|
// Verify that the buttons are hidden
|
|
assert.dom(GENERAL.button('Refresh list')).doesNotExist('Refresh List button is hidden');
|
|
assert.dom(GENERAL.button('Manage')).doesNotExist('Manage button is hidden');
|
|
});
|
|
|
|
test('it updates the namespace list after clicking "Refresh list"', async function (assert) {
|
|
this.owner.lookup('service:namespace').set('hasListPermissions', true);
|
|
|
|
const storeStub = this.owner.lookup('service:store');
|
|
sinon.stub(storeStub, 'findRecord').callsFake((modelType, id) => {
|
|
if (modelType === 'capabilities' && id === 'sys/namespaces/') {
|
|
return Promise.resolve(getMockCapabilitiesModel(true)); // Return the mock model
|
|
}
|
|
return Promise.reject();
|
|
});
|
|
|
|
await render(hbs`<NamespacePicker />`);
|
|
await click(GENERAL.toggleInput('namespace-picker'));
|
|
|
|
// Dynamically modify the `findNamespacesForUser.perform` method for this test
|
|
const namespaceService = this.owner.lookup('service:namespace');
|
|
namespaceService.set('findNamespacesForUser', {
|
|
perform: () => {
|
|
namespaceService.set('accessibleNamespaces', [
|
|
'parent1',
|
|
'parent1/child1',
|
|
'new-namespace', // Add a new namespace
|
|
]);
|
|
return Promise.resolve();
|
|
},
|
|
});
|
|
|
|
// Verify initial namespaces are displayed
|
|
assert.dom(GENERAL.button('parent1')).exists('Namespace "parent1" is displayed');
|
|
assert.dom(GENERAL.button('parent1/child1')).exists('Namespace "parent1/child1" is displayed');
|
|
assert.dom(GENERAL.button('root')).exists('Namespace "root" is displayed');
|
|
assert
|
|
.dom(GENERAL.button('new-namespace'))
|
|
.doesNotExist('Namespace "new-namespace" is not displayed initially');
|
|
|
|
// Click the "Refresh list" button
|
|
await click(GENERAL.button('Refresh list'));
|
|
|
|
// Verify the new namespace is displayed
|
|
assert
|
|
.dom(GENERAL.button('new-namespace'))
|
|
.exists('Namespace "new-namespace" is displayed after refreshing');
|
|
});
|
|
});
|