mirror of
https://github.com/datahub-project/datahub.git
synced 2025-08-26 10:06:13 +00:00
Merge pull request #842 from theseyi/first-fridays
update configuration for mirage. fixes test for authenticate request handler. updates tests. adds assertion got authenticate action
This commit is contained in:
commit
c80d843777
@ -1,6 +1,6 @@
|
|||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
import { inject } from '@ember/service';
|
import { inject } from '@ember/service';
|
||||||
import { getProperties, computed } from '@ember/object';
|
import { getProperties, computed, set } from '@ember/object';
|
||||||
import ComputedProperty, { oneWay } from '@ember/object/computed';
|
import ComputedProperty, { oneWay } from '@ember/object/computed';
|
||||||
import { baseCommentEditorOptions } from 'wherehows-web/constants';
|
import { baseCommentEditorOptions } from 'wherehows-web/constants';
|
||||||
import Notifications, { NotificationEvent } from 'wherehows-web/services/notifications';
|
import Notifications, { NotificationEvent } from 'wherehows-web/services/notifications';
|
||||||
@ -102,8 +102,12 @@ export default class DatasetDeprecation extends Component {
|
|||||||
const { onUpdateDeprecation } = this;
|
const { onUpdateDeprecation } = this;
|
||||||
|
|
||||||
if (onUpdateDeprecation) {
|
if (onUpdateDeprecation) {
|
||||||
|
const noteValue = deprecatedAlias ? deprecationNoteAlias : '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await onUpdateDeprecation(deprecatedAlias, deprecationNoteAlias);
|
await onUpdateDeprecation(deprecatedAlias, noteValue);
|
||||||
|
set(this, 'deprecationNoteAlias', noteValue);
|
||||||
|
|
||||||
notify(NotificationEvent.success, {
|
notify(NotificationEvent.success, {
|
||||||
content: 'Successfully updated deprecation status'
|
content: 'Successfully updated deprecation status'
|
||||||
});
|
});
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
const {
|
|
||||||
Component
|
|
||||||
} = Ember;
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
classNames: ['nacho-login-form'],
|
|
||||||
actions: {
|
|
||||||
/**
|
|
||||||
* Handle the login for submission
|
|
||||||
*/
|
|
||||||
userDidSubmit() {
|
|
||||||
// Trigger action on parent controller
|
|
||||||
this.get('onSubmit')();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
35
wherehows-web/app/components/login-form.ts
Normal file
35
wherehows-web/app/components/login-form.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import Component from '@ember/component';
|
||||||
|
import { get } from '@ember/object';
|
||||||
|
import { assert } from '@ember/debug';
|
||||||
|
|
||||||
|
export default class LoginForm extends Component {
|
||||||
|
classNames = ['nacho-login-form'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External action to be invoked on form submission
|
||||||
|
* @type {Function}
|
||||||
|
* @memberof LoginForm
|
||||||
|
*/
|
||||||
|
onSubmit: Function;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
|
||||||
|
// Ensure that the onSubmit action passed in on instantiation is a callable action
|
||||||
|
const typeOfOnSubmit = typeof this.onSubmit;
|
||||||
|
assert(
|
||||||
|
`Expected action onSubmit to be an function (Ember action), got ${typeOfOnSubmit}`,
|
||||||
|
typeOfOnSubmit === 'function'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
actions = {
|
||||||
|
/**
|
||||||
|
* Handle the login for submission
|
||||||
|
*/
|
||||||
|
userDidSubmit(this: LoginForm) {
|
||||||
|
// Trigger action on parent controller
|
||||||
|
get(this, 'onSubmit')();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -1,12 +1,6 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
const {
|
const { Controller, computed, get, setProperties, inject: { service } } = Ember;
|
||||||
Controller,
|
|
||||||
computed,
|
|
||||||
get,
|
|
||||||
setProperties,
|
|
||||||
inject: { service }
|
|
||||||
} = Ember;
|
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
session: service(),
|
session: service(),
|
||||||
@ -22,15 +16,11 @@ export default Controller.extend({
|
|||||||
* Using the session service, authenticate using the custom ldap authenticator
|
* Using the session service, authenticate using the custom ldap authenticator
|
||||||
*/
|
*/
|
||||||
authenticateUser() {
|
authenticateUser() {
|
||||||
const { username, password } = this.getProperties([
|
const { username, password } = this.getProperties(['username', 'password']);
|
||||||
'username',
|
|
||||||
'password'
|
|
||||||
]);
|
|
||||||
|
|
||||||
get(this, 'session')
|
get(this, 'session')
|
||||||
.authenticate('authenticator:custom-ldap', username, password)
|
.authenticate('authenticator:custom-ldap', username, password)
|
||||||
.catch(({ responseText = 'Bad Credentials' }) =>
|
.catch(({ responseText = 'Bad Credentials' }) => setProperties(this, { errorMessage: responseText }));
|
||||||
setProperties(this, { errorMessage: responseText }));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,32 +1,20 @@
|
|||||||
import { faker } from 'ember-cli-mirage';
|
import { faker } from 'ember-cli-mirage';
|
||||||
import { IFunctionRouteHandler, IMirageServer } from 'wherehows-web/typings/ember-cli-mirage';
|
import { IFunctionRouteHandler, IMirageServer } from 'wherehows-web/typings/ember-cli-mirage';
|
||||||
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
||||||
import { getConfig } from "./helpers/config";
|
import { getConfig } from 'wherehows-web/mirage/helpers/config';
|
||||||
|
import { getAuth } from 'wherehows-web/mirage/helpers/authenticate';
|
||||||
|
|
||||||
export default function(this: IMirageServer) {
|
export default function(this: IMirageServer) {
|
||||||
|
|
||||||
this.get('/config', getConfig);
|
this.get('/config', getConfig);
|
||||||
|
|
||||||
this.post('/authenticate', function({}, request: any) {
|
this.post('/authenticate', getAuth);
|
||||||
const username = JSON.parse(request.requestBody).username;
|
|
||||||
const password = JSON.parse(request.requestBody).password;
|
|
||||||
|
|
||||||
if (password === null || password === undefined) {
|
|
||||||
return 'Missing or invalid [credentials]';
|
|
||||||
} else if (password === 'invalidPassword') {
|
|
||||||
return 'Invalid Password';
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
status: ApiStatus.OK,
|
|
||||||
data: {username: username, uuid: faker.random.uuid()}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
this.namespace = '/api/v1';
|
this.namespace = '/api/v1';
|
||||||
|
|
||||||
interface IComplianceSuggestionsObject {
|
interface IComplianceSuggestionsObject {
|
||||||
complianceSuggestions: any;
|
complianceSuggestions: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.get('/datasets/:id/compliance/suggestions', function(
|
this.get('/datasets/:id/compliance/suggestions', function(
|
||||||
this: IFunctionRouteHandler,
|
this: IFunctionRouteHandler,
|
||||||
{ complianceSuggestions }: IComplianceSuggestionsObject
|
{ complianceSuggestions }: IComplianceSuggestionsObject
|
||||||
@ -44,9 +32,8 @@ export default function(this: IMirageServer) {
|
|||||||
interface IFlowsObject {
|
interface IFlowsObject {
|
||||||
flows: any;
|
flows: any;
|
||||||
}
|
}
|
||||||
this.get('/flows', function(
|
|
||||||
this: IFunctionRouteHandler,
|
this.get('/flows', function(this: IFunctionRouteHandler, { flows }: IFlowsObject, request: any) {
|
||||||
{ flows }: IFlowsObject, request: any) {
|
|
||||||
const { page } = request.queryParams;
|
const { page } = request.queryParams;
|
||||||
const flowsArr = this.serialize(flows.all());
|
const flowsArr = this.serialize(flows.all());
|
||||||
const count = faker.random.number({ min: 20000, max: 40000 });
|
const count = faker.random.number({ min: 20000, max: 40000 });
|
||||||
@ -59,7 +46,7 @@ export default function(this: IMirageServer) {
|
|||||||
flows: flowsArr,
|
flows: flowsArr,
|
||||||
itemsPerPage: itemsPerPage,
|
itemsPerPage: itemsPerPage,
|
||||||
page: page,
|
page: page,
|
||||||
totalPages: Math.round(count / itemsPerPage),
|
totalPages: Math.round(count / itemsPerPage)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -81,7 +68,10 @@ export default function(this: IMirageServer) {
|
|||||||
}
|
}
|
||||||
this.get('/datasets', function(
|
this.get('/datasets', function(
|
||||||
this: IFunctionRouteHandler,
|
this: IFunctionRouteHandler,
|
||||||
{ datasets }: IDatasetsObject, { owners }: IOwnersObject, request: any) {
|
{ datasets }: IDatasetsObject,
|
||||||
|
{ owners }: IOwnersObject,
|
||||||
|
request: any
|
||||||
|
) {
|
||||||
const { page } = request.queryParams;
|
const { page } = request.queryParams;
|
||||||
const datasetsArr = this.serialize(datasets.all());
|
const datasetsArr = this.serialize(datasets.all());
|
||||||
const ownersArr = this.serialize(owners.all());
|
const ownersArr = this.serialize(owners.all());
|
||||||
@ -99,7 +89,7 @@ export default function(this: IMirageServer) {
|
|||||||
page: page,
|
page: page,
|
||||||
itemsPerPage: itemsPerPage,
|
itemsPerPage: itemsPerPage,
|
||||||
totalPages: Math.round(count / itemsPerPage),
|
totalPages: Math.round(count / itemsPerPage),
|
||||||
datasets: newDatasetsArr,
|
datasets: newDatasetsArr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -141,8 +131,8 @@ export default function(this: IMirageServer) {
|
|||||||
email: testUser + '@linkedin.com',
|
email: testUser + '@linkedin.com',
|
||||||
name: testUser,
|
name: testUser,
|
||||||
userSetting: {
|
userSetting: {
|
||||||
"detailDefaultView": null,
|
detailDefaultView: null,
|
||||||
"defaultWatch":null
|
defaultWatch: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
status: ApiStatus.OK
|
status: ApiStatus.OK
|
||||||
@ -151,6 +141,4 @@ export default function(this: IMirageServer) {
|
|||||||
this.passthrough();
|
this.passthrough();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function testConfig(this: IMirageServer) {
|
export function testConfig(this: IMirageServer) {}
|
||||||
this.get('/config', getConfig);
|
|
||||||
}
|
|
||||||
|
33
wherehows-web/mirage/helpers/authenticate.ts
Normal file
33
wherehows-web/mirage/helpers/authenticate.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
||||||
|
import { Response, faker } from 'ember-cli-mirage';
|
||||||
|
|
||||||
|
type StringOrNullOrUndefined = string | null | void;
|
||||||
|
|
||||||
|
const textContentHeader = { 'Content-Type': 'text/plain; charset=utf-8' };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a config object for the config endpoint
|
||||||
|
* @param {object} _schema the auth table / factory object
|
||||||
|
* @param {requestBody} property on the request object passed in to mirage function handlers
|
||||||
|
* @return {{status: ApiStatus, data: object}}
|
||||||
|
*/
|
||||||
|
const getAuth = (_schema: {}, { requestBody }: { requestBody: string }) => {
|
||||||
|
const { username, password } = <{ username: StringOrNullOrUndefined; password: StringOrNullOrUndefined }>JSON.parse(
|
||||||
|
requestBody
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!password) {
|
||||||
|
return new Response(400, textContentHeader, 'Missing or invalid [credentials]');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password === 'invalidPassword') {
|
||||||
|
return new Response(401, textContentHeader, 'Invalid Password');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: ApiStatus.OK,
|
||||||
|
data: { username, uuid: faker.random.uuid() }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getAuth };
|
3
wherehows-web/mirage/models/authenticate.js
Normal file
3
wherehows-web/mirage/models/authenticate.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { Model } from 'ember-cli-mirage';
|
||||||
|
|
||||||
|
export default Model.extend({});
|
@ -1,14 +1,8 @@
|
|||||||
export default function(server) {
|
export default function(server) {
|
||||||
|
const fixtures = ['dataset-nodes', 'metric-metrics', 'user-entities'];
|
||||||
const fixtures = [
|
|
||||||
'dataset-nodes',
|
|
||||||
'metric-metrics',
|
|
||||||
'user-entities'
|
|
||||||
];
|
|
||||||
server.loadFixtures(...fixtures);
|
server.loadFixtures(...fixtures);
|
||||||
server.createList('complianceSuggestion', 5);
|
server.createList('complianceSuggestion', 5);
|
||||||
server.createList('owner', 6);
|
server.createList('owner', 6);
|
||||||
server.createList('dataset', 10);
|
server.createList('dataset', 10);
|
||||||
server.createList('flow', 10);
|
server.createList('flow', 10);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,12 +50,12 @@
|
|||||||
"ember-concurrency": "^0.8.10",
|
"ember-concurrency": "^0.8.10",
|
||||||
"ember-export-application-global": "^2.0.0",
|
"ember-export-application-global": "^2.0.0",
|
||||||
"ember-fetch": "^3.4.3",
|
"ember-fetch": "^3.4.3",
|
||||||
|
"ember-load-initializers": "^1.0.0",
|
||||||
"ember-lodash-shim": "^2.0.5",
|
"ember-lodash-shim": "^2.0.5",
|
||||||
"ember-metrics": "^0.12.1",
|
"ember-metrics": "^0.12.1",
|
||||||
"ember-pikaday": "^2.2.1",
|
"ember-pikaday": "^2.2.1",
|
||||||
"ember-redux-shim": "^1.1.1",
|
"ember-redux-shim": "^1.1.1",
|
||||||
"ember-redux-thunk-shim": "^1.1.2",
|
"ember-redux-thunk-shim": "^1.1.2",
|
||||||
"ember-load-initializers": "^1.0.0",
|
|
||||||
"ember-resolver": "^4.5.0",
|
"ember-resolver": "^4.5.0",
|
||||||
"ember-source": "~2.16.0",
|
"ember-source": "~2.16.0",
|
||||||
"ember-symbol-observable": "^0.1.2",
|
"ember-symbol-observable": "^0.1.2",
|
||||||
@ -67,12 +67,12 @@
|
|||||||
"eyeglass-restyle": "^1.1.0",
|
"eyeglass-restyle": "^1.1.0",
|
||||||
"husky": "^0.14.3",
|
"husky": "^0.14.3",
|
||||||
"lint-staged": "^4.3.0",
|
"lint-staged": "^4.3.0",
|
||||||
|
"loader.js": "^4.6.0",
|
||||||
"node-sass": "^4.5.3",
|
"node-sass": "^4.5.3",
|
||||||
"prettier": "^1.7.4",
|
"prettier": "^1.7.4",
|
||||||
"redux": "^3.6.0",
|
"redux": "^3.6.0",
|
||||||
"redux-thunk": "^2.2.0",
|
"redux-thunk": "^2.2.0",
|
||||||
"typescript": "^2.5.3",
|
"typescript": "^2.5.3"
|
||||||
"loader.js": "^4.6.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dynamic-link": "^0.2.3",
|
"dynamic-link": "^0.2.3",
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { test } from 'qunit';
|
import { test } from 'qunit';
|
||||||
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
||||||
|
import wait from 'ember-test-helpers/wait';
|
||||||
import {
|
import {
|
||||||
loginContainer,
|
loginContainer,
|
||||||
authenticationUrl,
|
authenticationUrl,
|
||||||
invalidCredentials,
|
invalidCredentials,
|
||||||
testUser,
|
testUser,
|
||||||
testPassword,
|
|
||||||
testPasswordInvalid
|
testPasswordInvalid
|
||||||
} from 'wherehows-web/tests/helpers/login/constants';
|
} from 'wherehows-web/tests/helpers/login/constants';
|
||||||
import {
|
import {
|
||||||
@ -40,7 +40,9 @@ test('should render login form', function(assert) {
|
|||||||
test('should display error message with empty credentials', async function(assert) {
|
test('should display error message with empty credentials', async function(assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
await fillIn(loginUserInput, testUser);
|
await fillIn(loginUserInput, testUser);
|
||||||
await click('button[type=submit]');
|
await click(loginSubmitButton);
|
||||||
|
|
||||||
|
await wait();
|
||||||
|
|
||||||
assert.ok(find('#login-error').text().length, 'error message element is rendered');
|
assert.ok(find('#login-error').text().length, 'error message element is rendered');
|
||||||
|
|
||||||
@ -48,31 +50,26 @@ test('should display error message with empty credentials', async function(asser
|
|||||||
find('#login-error')
|
find('#login-error')
|
||||||
.text()
|
.text()
|
||||||
.trim(),
|
.trim(),
|
||||||
invalidCredentials
|
invalidCredentials,
|
||||||
|
'displays missing or invalid credentials message'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Login with an empty password', async function(assert) {
|
test('should display invalid password message with invalid password entered', async function(assert) {
|
||||||
await fillIn(loginUserInput, testUser);
|
assert.expect(2);
|
||||||
await click(loginSubmitButton);
|
|
||||||
|
|
||||||
assert.equal(
|
|
||||||
find('#login-error')
|
|
||||||
.text()
|
|
||||||
.trim(),
|
|
||||||
invalidCredentials
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Login with an invalid password', async function(assert) {
|
|
||||||
await fillIn(loginUserInput, testUser);
|
await fillIn(loginUserInput, testUser);
|
||||||
await fillIn(loginPasswordInput, testPasswordInvalid);
|
await fillIn(loginPasswordInput, testPasswordInvalid);
|
||||||
await click(loginSubmitButton);
|
await click(loginSubmitButton);
|
||||||
|
|
||||||
|
await wait();
|
||||||
|
|
||||||
|
assert.ok(find('#login-error').text().length, 'error message element is rendered');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
find('#login-error')
|
find('#login-error')
|
||||||
.text()
|
.text()
|
||||||
.trim(),
|
.trim(),
|
||||||
'Invalid Password'
|
'Invalid Password',
|
||||||
|
'displays invalid password message in error message container'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
import { moduleForComponent, test } from 'ember-qunit';
|
||||||
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
import { run } from '@ember/runloop';
|
||||||
|
|
||||||
|
moduleForComponent('login-form', 'Integration | Component | login form', {
|
||||||
|
integration: true
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it renders', function(assert) {
|
||||||
|
this.set('authenticateUser', () => {});
|
||||||
|
this.render(hbs`{{login-form onSubmit=(action authenticateUser)}}`);
|
||||||
|
|
||||||
|
assert.equal(this.$('#login-username').length, 1, 'has an input for username');
|
||||||
|
assert.equal(this.$('#login-password').length, 1, 'has an input for password');
|
||||||
|
assert.equal(this.$('[type=submit]').length, 1, 'has a button for submission');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('triggers the onSubmit action when clicked', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
let submitActionCallCount = false;
|
||||||
|
|
||||||
|
this.set('authenticateUser', function() {
|
||||||
|
submitActionCallCount = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.render(hbs`{{login-form onSubmit=(action authenticateUser)}}`);
|
||||||
|
|
||||||
|
assert.equal(submitActionCallCount, false, 'submit action is not called on render');
|
||||||
|
run(() => document.querySelector('.nacho-login-form [type=submit]').click());
|
||||||
|
|
||||||
|
assert.equal(submitActionCallCount, true, 'submit action is called once');
|
||||||
|
});
|
@ -20,7 +20,8 @@
|
|||||||
"downlevelIteration": true,
|
"downlevelIteration": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"wherehows-web/*": ["app/*"],
|
"wherehows-web/*": ["app/*"],
|
||||||
"wherehows-web/tests/*": ["tests/*"]
|
"wherehows-web/tests/*": ["tests/*"],
|
||||||
|
"wherehows-web/mirage/*": ["mirage/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["app/**/*", "tests/**/*", "mirage/**/*"],
|
"include": ["app/**/*", "tests/**/*", "mirage/**/*"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user