Initial commit

This commit is contained in:
zhongjin
2020-06-15 10:58:47 +08:00
commit 4f1dfe7564
8590 changed files with 1516878 additions and 0 deletions
@@ -0,0 +1,178 @@
const $ = require('jquery');
const AddOrRemoveGroupUsersFiltersExtraView = require('dashboard/views/organization/groups-admin/filters/add-or-remove-group-users-filters-extra-view');
const PasswordValidatedForm = require('dashboard/helpers/password-validated-form');
const AddGroupUsersView = require('dashboard/views/organization/groups-admin/add-group-users/add-group-users-view');
const configModel = require('fixtures/dashboard/config-model.fixture');
const UserModel = require('dashboard/data/user-model');
const GroupModel = require('dashboard/data/group-model');
const OrganizationModel = require('dashboard/data/organization-model');
const PASSWORD = 'password';
describe('organization/groups-admin/add-or-remove-group-users-filters-extra-view', function () {
beforeEach(function () {
spyOn(PasswordValidatedForm, 'showPasswordModal').and.callFake(
function (options) {
options.onPasswordTyped && options.onPasswordTyped(PASSWORD);
}
);
this.user = new UserModel({
id: 'user-id',
username: 'pepe',
actions: {},
needs_password_confirmation: true
}, {});
this.organization = new OrganizationModel({
id: 'org-id',
users: [{
id: 'abc-123',
username: 'paco'
},
{
id: 'abc-456',
username: 'pepe'
}]
}, { configModel });
this.user.setOrganization(this.organization);
this.group = new GroupModel({
id: 'g1',
organization: this.user.organization,
users: [{
id: 'u1',
username: 'pachi'
}]
}, { configModel });
spyOn(AddGroupUsersView.prototype, 'initialize').and.callThrough();
this.view = new AddOrRemoveGroupUsersFiltersExtraView({
group: this.group,
orgUsers: this.user.organization.users,
userModel: this.user
});
this.view.render();
});
afterEach(function () {
// The Dialog closing action occurs within a 120ms delay, so we
// remove it manually instead of waiting for the dialog to close
const dialog = document.querySelector('.Dialog');
if (dialog) {
dialog.remove();
}
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
it('should not open dialog to add users just yet', function () {
expect(AddGroupUsersView.prototype.initialize).not.toHaveBeenCalled();
});
it('should show the add users button', function () {
expect(this.view.$('.js-add-users').attr('style')).toBeUndefined();
expect(this.view.$('.js-rm-users').attr('style')).toContain('display: none');
});
describe('when click add', function () {
beforeEach(function () {
this.view.$('.js-add-users').click();
});
it('should open dialog to add users', function () {
expect(AddGroupUsersView.prototype.initialize).toHaveBeenCalled();
});
});
describe('when at least one user is selected', function () {
beforeEach(function () {
this.group.users.first().set('selected', true);
});
it('should change the subheader to show remove button', function () {
expect(this.view.$('.js-add-users').attr('style')).toContain('display: none');
expect(this.view.$('.js-rm-users').attr('style')).not.toContain('none');
});
describe('when click remove', function () {
beforeEach(function () {
jasmine.clock().install(); // due to modal animations
this.jqXHR = $.Deferred();
spyOn(this.group.users, 'removeInBatch').and.returnValue(this.jqXHR);
this.view.$('.js-rm-users').click();
jasmine.clock().tick(1000);
});
afterEach(function () {
jasmine.clock().uninstall();
});
it('should require password confirmation if needed', function () {
expect(PasswordValidatedForm.showPasswordModal).toHaveBeenCalled();
});
it('should bypass password confirmation when needs_password_validation is false', function () {
PasswordValidatedForm.showPasswordModal.calls.reset();
const userModel = new UserModel({
needs_password_confirmation: false
});
this.view = new AddOrRemoveGroupUsersFiltersExtraView({
group: this.group,
orgUsers: this.user.organization.users,
userModel
});
expect(PasswordValidatedForm.showPasswordModal).not.toHaveBeenCalled();
});
it('should call group users collection to remove them in batch', function () {
expect(this.group.users.removeInBatch).toHaveBeenCalled();
expect(this.group.users.removeInBatch).toHaveBeenCalledWith(jasmine.any(Array), jasmine.any(String));
expect(this.group.users.removeInBatch).toHaveBeenCalledWith(['u1'], PASSWORD);
});
it('should show removing users loader in a modal', function () {
expect($('.Dialog').text()).toContain('Removing users');
});
describe('when users are removed', function () {
beforeEach(function () {
this.jqXHR.resolve();
jasmine.clock().tick(1000);
});
it('should close loading modal', function () {
expect($('.Dialog').length).toEqual(0);
});
});
describe('when fails to remove users', function () {
beforeEach(function () {
this.jqXHR.reject();
jasmine.clock().tick(1000);
});
it('should close loading modal', function () {
expect($('.Dialog').text()).not.toContain('Removing users');
});
it('should show error modal', function () {
expect($('.Dialog').text()).toContain('error');
});
});
});
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,85 @@
const FlashMessageModel = require('dashboard/data/flash-message-model');
const CreateGroupView = require('dashboard/views/organization/groups-admin/create-group/create-group-view');
const GroupModel = require('dashboard/data/group-model');
const configModel = require('fixtures/dashboard/config-model.fixture');
describe('organization/groups-admin/create-group-view', function () {
beforeEach(function () {
this.group = new GroupModel({}, { configModel });
spyOn(this.group, 'save');
this.onCreatedSpy = jasmine.createSpy('onCreated callback');
this.flashMessageModel = new FlashMessageModel();
this.view = new CreateGroupView({
configModel,
group: this.group,
onCreated: this.onCreatedSpy,
flashMessageModel: this.flashMessageModel
});
this.view.render();
});
it('should render input', function () {
expect(this.view.$('input').length > 0).toBe(true);
});
describe('when click create group', function () {
it('should not try to save group if has no name', function () {
this.view.$('.js-create').click();
expect(this.group.save).not.toHaveBeenCalled();
});
describe('when has written a name', function () {
beforeEach(function () {
this.view.$('.js-name').val('foobar');
this.view.$('.js-create').click();
});
it('should try to create group', function () {
expect(this.group.save).toHaveBeenCalled();
});
it('should show loading meanwhile', function () {
expect(this.innerHTML()).toContain('Creating group');
});
it('should not add to collection until got response', function () {
expect(this.group.save.calls.argsFor(0)[1].wait).toBe(true);
});
describe('when create succeeds', function () {
beforeEach(function () {
this.group.save.calls.argsFor(0)[1].success();
});
it('should call onCreated callback', function () {
expect(this.onCreatedSpy).toHaveBeenCalled();
});
});
describe('when create fails', function () {
beforeEach(function () {
spyOn(this.flashMessageModel, 'show');
this.group.save.calls.argsFor(0)[1].error(this.group, {responseText: '{"errors": ["ERR!"]}'});
});
it('should show form again', function () {
expect(this.innerHTML()).not.toContain('Creating group');
});
it('should show error', function () {
expect(this.flashMessageModel.show).toHaveBeenCalledWith('ERR!', 'error');
});
});
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,159 @@
const FlashMessageModel = require('dashboard/data/flash-message-model');
const GroupModel = require('dashboard/data/group-model');
const PasswordValidatedForm = require('dashboard/helpers/password-validated-form');
const ModalsServiceModel = require('builder/components/modals/modals-service-model');
const EditGroupView = require('dashboard/views/organization/groups-admin/edit-group/edit-group-view');
const configModel = require('fixtures/dashboard/config-model.fixture');
const UserModel = require('fixtures/dashboard/user-model.fixture');
describe('organization/groups-admin/edit-group-view', function () {
beforeEach(function () {
this.group = new GroupModel({
id: 'g1',
display_name: 'my group'
}, { configModel });
spyOn(this.group, 'save');
spyOn(PasswordValidatedForm, 'showPasswordModal').and.callFake(
function (options) {
options.onPasswordTyped && options.onPasswordTyped();
}
);
this.onSavedSpy = jasmine.createSpy('onSaved callback');
this.onDeletedSpy = jasmine.createSpy('onDeleted callback');
this.flashMessageModel = new FlashMessageModel();
this.view = new EditGroupView({
flashMessageModel: this.flashMessageModel,
group: this.group,
userModel: new UserModel(),
modals: new ModalsServiceModel(),
onSaved: this.onSavedSpy,
onDeleted: this.onDeletedSpy
});
this.view.render();
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
describe('when click save', function () {
it('should not try to save group if has no name', function () {
this.view.$('.js-name').val('');
this.view.$('.js-save').click();
expect(this.group.save).not.toHaveBeenCalled();
});
describe('when has changed name', function () {
beforeEach(function () {
this.view.$('.js-name').val('new name');
this.view.$('.js-save').click();
});
it('should try to save group', function () {
expect(this.group.save).toHaveBeenCalled();
expect(this.group.save).toHaveBeenCalledWith({
display_name: 'new name'
}, jasmine.any(Object));
});
it('should show loading meanwhile', function () {
expect(this.innerHTML()).toContain('Saving');
});
it('should not update model until got response back', function () {
expect(this.group.save.calls.argsFor(0)[1].wait).toBe(true);
});
describe('when save succeeds', function () {
beforeEach(function () {
this.group.set({
id: 'g1'
});
this.group.save.calls.argsFor(0)[1].success();
});
it('should call onSaved callback', function () {
expect(this.onSavedSpy).toHaveBeenCalled();
});
});
describe('when save fails', function () {
beforeEach(function () {
spyOn(this.flashMessageModel, 'show');
this.group.save.calls.argsFor(0)[1].error(this.group, {responseText: '{"errors": ["ERR!"]}'});
});
it('should show form again', function () {
expect(this.view.$('input').length > 0).toBe(true);
});
it('should show error', function () {
expect(this.flashMessageModel.show).toHaveBeenCalledWith('ERR!', 'error');
});
});
});
});
describe('when click delete group', function () {
beforeEach(function () {
spyOn(this.group, 'destroy');
this.view.$('.js-delete').click();
});
it('should require password confirmation if needed', function () {
expect(PasswordValidatedForm.showPasswordModal).toHaveBeenCalled();
});
it('should bypass password confirmation when needs_password_validation is false', function () {
PasswordValidatedForm.showPasswordModal.calls.reset();
this.view = new EditGroupView({
flashMessageModel: this.flashMessageModel,
group: this.group,
userModel: new UserModel({ needs_password_validation: false }),
modals: new ModalsServiceModel(),
onSaved: this.onSavedSpy,
onDeleted: this.onDeletedSpy
});
expect(PasswordValidatedForm.showPasswordModal).not.toHaveBeenCalled();
});
it('should change to loading while destroying', function () {
expect(this.innerHTML()).toContain('Deleting');
});
it('should not remove from collection until response confirms it deleteted', function () {
expect(this.group.destroy.calls.argsFor(0)[0].wait).toBe(true);
});
describe('when deleted', function () {
beforeEach(function () {
this.group.destroy.calls.argsFor(0)[0].success();
});
it('should call onDeleted callback', function () {
expect(this.onDeletedSpy).toHaveBeenCalled();
});
});
describe('when deletion fails', function () {
beforeEach(function () {
this.group.destroy.calls.argsFor(0)[0].error();
});
it('should show form again', function () {
expect(this.view.$('input').length > 0).toBe(true);
});
});
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,167 @@
const $ = require('jquery');
const EmptyGroupFiltersExtraView = require('dashboard/views/organization/groups-admin/filters/empty-group-filters-extra-view');
const UserModel = require('dashboard/data/user-model');
const GroupModel = require('dashboard/data/group-model');
const OrganizationModel = require('dashboard/data/organization-model');
const PasswordValidatedForm = require('dashboard/helpers/password-validated-form');
const configModel = require('fixtures/dashboard/config-model.fixture');
const PASSWORD = 'password';
describe('organization/groups_admin/empty_group_filters_extra_view', function () {
beforeEach(function () {
spyOn(PasswordValidatedForm, 'showPasswordModal').and.callFake(
function (options) {
options.onPasswordTyped && options.onPasswordTyped(PASSWORD);
}
);
this.organization = new OrganizationModel({
id: 'org-id',
users: [{
id: 'ou-1',
username: 'paco'
},
{
id: 'ou-2',
username: 'pepe'
}]
}, { configModel });
this.user = new UserModel({
id: 'user-id',
username: 'pepe',
actions: {},
needs_password_confirmation: true
});
this.user.setOrganization(this.organization);
this.group = new GroupModel({
id: 'g1',
organization: this.user.organization,
users: [{
id: 'gu-1',
username: 'pachi'
}]
}, { configModel });
this.groupUsers = this.group.users;
spyOn(this.groupUsers, 'addInBatch');
this.orgUsers = this.user.organization.users;
this.view = new EmptyGroupFiltersExtraView({
groupUsers: this.groupUsers,
orgUsers: this.orgUsers,
userModel: this.user
});
this.view.render();
});
afterEach(function () {
// The Dialog closing action occurs within a 120ms delay, so we
// remove it manually instead of waiting for the dialog to close
var dialog = document.querySelector('.Dialog');
if (dialog) {
dialog.remove();
}
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
it('should show the add-users button disabled', function () {
expect(this.view.$('.js-add-users').hasClass('is-disabled')).toBe(true);
});
it('should do nothing on click add-button', function () {
this.view.$('.js-add-users').click();
expect(this.groupUsers.addInBatch).not.toHaveBeenCalled();
});
describe('when at least one user is selected', function () {
beforeEach(function () {
this.orgUsers.first().set('selected', true);
});
it('should change the subheader to show add button', function () {
expect(this.view.$('.js-add-users').hasClass('is-disabled')).toBe(false);
});
describe('when click add', function () {
beforeEach(function () {
jasmine.clock().install(); // due to modal animations
this.jqXHR = $.Deferred();
this.groupUsers.addInBatch.and.returnValue(this.jqXHR);
this.view.$('.js-add-users').click();
jasmine.clock().tick(1000);
});
afterEach(function () {
jasmine.clock().uninstall();
});
it('should require password confirmation if needed', function () {
expect(PasswordValidatedForm.showPasswordModal).toHaveBeenCalled();
});
it('should bypass password confirmation when needs_password_validation is false', function () {
PasswordValidatedForm.showPasswordModal.calls.reset();
const userModel = new UserModel({
needs_password_confirmation: false
});
this.view = new EmptyGroupFiltersExtraView({
groupUsers: this.groupUsers,
orgUsers: this.orgUsers,
userModel
});
expect(PasswordValidatedForm.showPasswordModal).not.toHaveBeenCalled();
});
it('should call group users collection to add them in batch', function () {
expect(this.group.users.addInBatch).toHaveBeenCalled();
expect(this.group.users.addInBatch).toHaveBeenCalledWith(jasmine.any(Array), jasmine.any(String));
expect(this.group.users.addInBatch).toHaveBeenCalledWith(['ou-1'], PASSWORD);
});
it('should show removing users loader in a modal', function () {
expect($('.Dialog').text()).toContain('Adding');
});
describe('when users are added', function () {
beforeEach(function () {
this.jqXHR.resolve();
jasmine.clock().tick(1000);
});
it('should close loading modal', function () {
expect($('.Dialog').length).toEqual(0);
});
});
describe('when fails to add users', function () {
beforeEach(function () {
this.jqXHR.reject();
jasmine.clock().tick(1000);
});
it('should close loading modal', function () {
expect($('.Dialog').text()).not.toContain('Adding');
});
it('should show error modal', function () {
expect($('.Dialog').text()).toContain('error');
});
});
});
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,92 @@
const GroupHeaderView = require('dashboard/views/organization/groups-admin/group-header/group-header-view');
const GroupModel = require('dashboard/data/group-model');
const UrlModel = require('dashboard/data/url-model');
const configModel = require('fixtures/dashboard/config-model.fixture');
describe('dashboard/views/organization/groups-admin/group-header-view', function () {
beforeEach(function () {
this.setupView = function () {
this.group = new GroupModel({}, { configModel });
this.urls = {
root: new UrlModel({ base_url: 'fake-root-url' }),
users: new UrlModel({ base_url: 'fake-users-url' }),
edit: new UrlModel({ base_url: 'fake-edit-url' })
};
this.urls.users.isCurrent = true;
spyOn(GroupHeaderView.prototype, 'initialize').and.callThrough();
this.view = new GroupHeaderView({
group: this.group,
urls: this.urls
});
this.view.render();
};
});
describe('when group is new', function () {
beforeEach(function () {
this.setupView();
});
it('should render the fallback text as title', function () {
expect(this.innerHTML()).toContain('Create new group');
});
it('should render back button to root', function () {
expect(this.view.$('.Filters-group a.u-actionTextColor').attr('href')).toEqual('fake-root-url');
});
it('should not render the users tab', function () {
expect(this.innerHTML()).not.toMatch('\sUser');
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
describe('when group already exist', function () {
beforeEach(function () {
this.setupView();
this.group.set({
id: 'g1',
display_name: 'my group'
});
});
it('should render the group display name as title', function () {
expect(this.innerHTML()).toContain('my group');
});
it('should render back button to root', function () {
expect(this.view.$('.Filters-group a.u-actionTextColor').attr('href')).toEqual('fake-root-url');
});
it('should render back button to users if is not on users url', function () {
this.urls.users.isCurrent = false;
this.view.render();
expect(this.view.$('.Filters-group a.u-actionTextColor').attr('href')).toEqual('fake-users-url');
});
it('should render the menu', function () {
expect(this.innerHTML()).toContain('User');
});
it('should only render users count if has any', function () {
expect(this.innerHTML()).not.toContain('0 Users');
this.group.users.reset([{}]);
expect(this.innerHTML()).toContain('1 User');
this.group.users.reset([{}, {}, {}]);
expect(this.innerHTML()).toContain('3 Users');
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,35 @@
const Backbone = require('backbone');
const CoreView = require('backbone/core-view');
const GroupsMainView = require('dashboard/views/organization/groups-admin/groups-main-view');
describe('dashboard/views/organization/groups-admin/groups-main-view', function () {
beforeEach(function () {
this.contentView = new CoreView();
spyOn(this.contentView, 'render').and.callThrough();
this.routerModel = new Backbone.Model({
view: this.contentView
});
this.router = new Backbone.Model();
this.router.model = this.routerModel;
this.view = new GroupsMainView({
routerModel: this.router,
groups: this.groups
});
this.view.render();
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
it('should render the view given by router model', function () {
expect(this.contentView.render).toHaveBeenCalled();
expect(this.view.el).toEqual(this.contentView.el.parentNode);
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,139 @@
const GroupUsersView = require('dashboard/views/organization/groups-admin/group-users/group-users-view');
const GroupModel = require('dashboard/data/group-model');
const UserModel = require('dashboard/data/user-model');
const OrganizationModel = require('dashboard/data/organization-model');
const configModel = require('fixtures/dashboard/config-model.fixture');
describe('dashboard/organization/views/groups-admin/group-users/group-users-view', function () {
beforeEach(function () {
this.organization = new OrganizationModel({
id: 'org-id',
users: [{
id: 'abc-123',
username: 'paco'
},
{
id: 'abc-456',
username: 'pepe'
}]
}, { configModel, currentUserId: 'user-id' });
this.user = new UserModel({
id: 'user-id',
username: 'pepe',
actions: {}
});
this.user.setOrganization(this.organization);
this.group = new GroupModel({
id: 'g1',
organization: this.user.organization,
users: [{
id: 'u1',
username: 'pachi'
}]
}, { configModel });
this.groupUsers = this.group.users;
this.groupUsers.sync = (a, b, opts) => {
this.syncOpts = opts;
};
this.view = new GroupUsersView({
group: this.group,
orgUsers: this.user.organization.users,
userModel: new UserModel()
});
this.view.render();
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
it('should render a loading view initially', function () {
expect(this.innerHTML()).toContain('Getting users');
});
describe('when group users are fetched', function () {
describe('when there are no group users', function () {
beforeEach(function () {
this.syncOpts.success({
users: [],
total_user_entries: 0,
total_entries: 0
});
});
it('should render the empty view', function () {
expect(this.innerHTML()).not.toContain('Remove'); // btn
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
describe('when group users are added', function () {
beforeEach(function () {
this.syncOpts.success({
users: [{
id: 'gu-1',
username: 'pepito'
}],
total_user_entries: 1,
total_entries: 1
});
this.groupUsers.fetch();
});
it('should render the group users', function () {
expect(this.innerHTML()).toContain('pepito');
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
});
describe('when there are at least one group user', function () {
beforeEach(function () {
this.syncOpts.success({
users: [{
id: 'gu-2',
username: 'bollibompa'
}],
total_user_entries: 1,
total_entries: 1
});
});
it('should render the group users', function () {
expect(this.innerHTML()).toContain('bollibompa');
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
describe('when group is emptied', function () {
beforeEach(function () {
this.syncOpts.success({
users: [],
total_user_entries: 0,
total_entries: 0
});
this.groupUsers.fetch();
});
it('should render the empty view', function () {
expect(this.innerHTML()).not.toContain('Remove'); // btn
expect(this.innerHTML()).not.toContain('bollibompa');
});
});
});
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,48 @@
const GroupView = require('dashboard/views/organization/groups-admin/group-view/group-view');
const GroupModel = require('dashboard/data/group-model');
const configModel = require('fixtures/dashboard/config-model.fixture');
describe('organization/groups_admin/group_view', function () {
beforeEach(function () {
this.group = new GroupModel({
display_name: 'foobar',
shared_tables_count: 42,
shared_maps_count: 37,
users: [{
id: 'u1',
name: 'pepe'
}]
}, { configModel });
this.view = new GroupView({
model: this.group,
url: 'group-url'
});
this.view.render();
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
it('should render the title', function () {
expect(this.innerHTML()).toContain('foobar');
});
it('should render the URL', function () {
expect(this.innerHTML()).toContain('href="group-url"');
});
it('should render the shared maps/datasets counts', function () {
expect(this.innerHTML()).toContain('42 shared datasets');
expect(this.innerHTML()).toContain('37 shared maps');
});
it('should render a preview of the users', function () {
expect(this.innerHTML()).toContain('pepe');
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,106 @@
const RouterModel = require('dashboard/views/organization/groups-admin/router-model');
const OrganizationGroupsCollection = require('dashboard/data/organization-groups-collection');
const OrganizationModel = require('dashboard/data/organization-model');
const GroupModel = require('dashboard/data/group-model');
const UserModel = require('dashboard/data/user-model');
const configModel = require('fixtures/dashboard/config-model.fixture');
describe('dashboard/data/router-model', function () {
beforeEach(function () {
const organization = new OrganizationModel({
owner: {
id: 123
}
}, { configModel });
const user = new UserModel({
id: 123,
base_url: 'https://carto.com/user/paco',
username: 'paco'
});
user.setOrganization(organization);
this.groups = new OrganizationGroupsCollection([], {
organization: user.organization,
configModel
});
this.model = new RouterModel();
});
describe('.createGroupView', function () {
beforeEach(function () {
this.groups.add({
id: 'g1',
display_name: 'group that i already fetched'
});
this.fetchedCallbackSpy = jasmine.createSpy('fetchedCallback');
});
describe('when given a id of a group that already is fetched', function () {
beforeEach(function () {
this.model.createGroupView(this.groups, 'g1', this.fetchedCallbackSpy);
});
it('should call the fetched callback right away with the corresponding group', function () {
expect(this.fetchedCallbackSpy).toHaveBeenCalled();
expect(this.fetchedCallbackSpy).toHaveBeenCalledWith(this.groups.first());
});
});
describe('when given a id of a group that is not yet fetched', function () {
beforeEach(function () {
spyOn(GroupModel.prototype, 'fetch');
this.model.createGroupView(this.groups, 'other', this.fetchedCallbackSpy);
});
it('should fetch the group first', function () {
expect(GroupModel.prototype.fetch).toHaveBeenCalled();
expect(this.fetchedCallbackSpy).not.toHaveBeenCalled();
});
it('should fetch w/ users', function () {
expect(GroupModel.prototype.fetch.calls.argsFor(0)[0].data.fetch_users).toBe(true);
});
describe('when fetch succeeds', function () {
beforeEach(function () {
GroupModel.prototype.fetch.calls.argsFor(0)[0].success();
});
it('should add the group to the collection', function () {
expect(this.groups.get('other')).toBeDefined();
});
it('should call the fetched callback with the new group', function () {
expect(this.fetchedCallbackSpy).toHaveBeenCalled();
expect(this.fetchedCallbackSpy).toHaveBeenCalledWith(this.groups.get('other'));
});
});
describe('when fetch fails', function () {
beforeEach(function () {
GroupModel.prototype.fetch.calls.argsFor(0)[0].error();
});
it('should create a generic error view', function () {
var view = this.model.get('view');
view.render();
expect(this.innerHTML(view)).toContain('error');
});
});
});
});
describe('.createLoadingView', function () {
beforeEach(function () {
this.model.createLoadingView('Loading something');
});
it('should create a loading view', function () {
var view = this.model.get('view');
view.render();
expect(this.innerHTML(view)).toContain('Loading something');
});
});
});
@@ -0,0 +1,57 @@
const Router = require('dashboard/common/router-organization-groups');
const UserModel = require('dashboard/data/user-model');
const OrganizationGroupsCollection = require('dashboard/data/organization-groups-collection');
const OrganizationModel = require('dashboard/data/organization-model');
const FlashMessageModel = require('dashboard/data/flash-message-model');
const ModalsServiceModel = require('builder/components/modals/modals-service-model');
const configModel = require('fixtures/dashboard/config-model.fixture');
describe('dashboard/common/router-organization-groups', function () {
beforeEach(function () {
const organization = new OrganizationModel({
owner: {
id: 123
}
}, { configModel });
const userModel = new UserModel({
id: 123,
base_url: 'https://carto.com/user/paco',
username: 'paco',
org_admin: true
});
userModel.setOrganization(organization);
this.groups = new OrganizationGroupsCollection([], {
organization: userModel.organization,
configModel
});
this.flashMessageModel = new FlashMessageModel();
this.router = new Router({
userModel,
flashMessageModel: this.flashMessageModel,
rootUrl: userModel.viewUrl().organization().groups(),
groups: this.groups,
modals: new ModalsServiceModel()
});
});
describe('.normalizeFragmentOrUrl', function () {
it('should return the normalized pathname for URLs matching current scope', function () {
expect(this.router.normalizeFragmentOrUrl('https://carto.com/user/paco/organization/groups/new')).toEqual('/new');
expect(this.router.normalizeFragmentOrUrl('https://carto.com/user/paco/organization/groups/edit/123')).toEqual('/edit/123');
});
it('should return full URL for non-matching URLs', function () {
expect(this.router.normalizeFragmentOrUrl('https://carto.com/user/paco/somewhere/else')).toEqual('https://carto.com/user/paco/somewhere/else');
});
});
it('should render a generic loading view for starters', function () {
var view = this.router.model.get('view');
view.render();
expect(this.innerHTML(view)).toContain('Loading view');
});
});