+ {{skills-typeahead
centered=true
selectSkill=(action toggleSkill)
skillsList=projectSkillsList
diff --git a/app/templates/start/skills.hbs b/app/templates/start/skills.hbs
index f14513fc8..45b42ca95 100644
--- a/app/templates/start/skills.hbs
+++ b/app/templates/start/skills.hbs
@@ -17,8 +17,8 @@
{{/each}}
- {{skills-input
+
+ {{skills-typeahead
centered=true
selectSkill=(action selectSkill)
skillsList=userSkillsList
diff --git a/app/utils/records-list.js b/app/utils/records-list.js
new file mode 100644
index 000000000..bd7cbb1fd
--- /dev/null
+++ b/app/utils/records-list.js
@@ -0,0 +1,70 @@
+import Ember from 'ember';
+
+const { get } = Ember;
+
+export default {
+ /**
+ Returns `true` or `false` depending on whether an array of models contains
+ the target model instance.
+ @method contains
+ @param {[DS.Model]} records The records to search
+ @param {DS.Model} target The target model
+ @return {Boolean} `true` if found, otherwise `false`
+ @public
+ */
+ contains(records, target) {
+ if (records) {
+ return records.any((found) => {
+ let targetId = get(target, 'id');
+ let targetModelName = get(target, 'constructor.modelName')
+ || get(target, 'content.constructor.modelName');
+ let foundId = found.belongsTo(targetModelName).id();
+
+ return (foundId === targetId);
+ });
+ } else {
+ false;
+ }
+ },
+
+ /**
+ Returns the first record within an array of join model relationships
+ for the given target and relationship. For example given `user-skill`
+ records, we can pass in a `skill` as `target` and a `user` as the
+ relationship.
+ @method find
+ @param {[DS.Model]} records The relationship records to search
+ @param {DS.Model} target The target model
+ @param {DS.Model} relationship The relationship model
+ @return {DS.Model} Found item or `undefined`
+ @public
+ */
+ find(records, target, relationship) {
+ if (records) {
+ return records.find((found) => {
+ // Get relationship id and model name
+ let relationshipId = get(relationship, 'id');
+ let relationshipModelName = get(relationship, 'constructor.modelName')
+ || get(relationship, 'content.constructor.modelName');
+
+ // Get target id and model name
+ let targetId = get(target, 'id');
+ let targetModelName = get(target, 'constructor.modelName')
+ || get(target, 'content.constructor.modelName');
+
+ // Exit early with `false` if we're missing values
+ if (!(relationshipId && relationshipModelName && targetId && targetModelName)) {
+ return false;
+ }
+
+ // Get the id of the found model instance and
+ // get the id of the found model's relationship model instance
+ let foundId = found.belongsTo(targetModelName).id();
+ let foundRelationshipId = found.belongsTo(relationshipModelName).id();
+
+ return (foundRelationshipId === relationshipId) // relationships match
+ && (foundId === targetId); // found matches target
+ });
+ }
+ }
+};
diff --git a/app/utils/skills-list.js b/app/utils/skills-list.js
deleted file mode 100644
index b692cb6b7..000000000
--- a/app/utils/skills-list.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import Ember from 'ember';
-
-const {
- get
-} = Ember;
-
-let skillsList = {
- find(skills, skill, relationship) {
- if (skills) {
- return skills.find((item) => {
- let modelName = get(item, 'constructor.modelName');
- return _matchForModelName(modelName, item, skill, relationship);
- });
- }
- },
-
- contains(skills, skill) {
- if (skills) {
- return skills.any((item) => {
- let itemSkillId = item.belongsTo('skill').id();
- let skillId = get(skill, 'id');
- return (itemSkillId === skillId);
- });
- } else {
- false;
- }
- }
-};
-
-function _matchForModelName(modelName, item, skill, relationship) {
- let relationshipName = get(relationship, 'constructor.modelName');
- return _matchWithRelationship(item, skill, relationship, relationshipName);
-}
-
-function _matchWithRelationship(item, skill, relationship, relationshipName) {
- let itemRelationshipId = item.belongsTo(relationshipName).id();
- let itemSkillId = item.belongsTo('skill').id();
- let relationshipId = get(relationship, 'id');
- let skillId = get(skill, 'id');
- return (itemRelationshipId === relationshipId) && (itemSkillId === skillId);
-}
-
-export default skillsList;
diff --git a/tests/acceptance/onboarding-test.js b/tests/acceptance/onboarding-test.js
index 0570f5fb7..189768a9b 100644
--- a/tests/acceptance/onboarding-test.js
+++ b/tests/acceptance/onboarding-test.js
@@ -96,13 +96,13 @@ test('A user can onboard as expected', function(assert) {
andThen(() => {
assert.equal(currentURL(), '/start/skills');
- onboardingPage.skillsInput.fillIn('ru');
+ onboardingPage.skillsTypeahead.fillIn('ru');
});
andThen(() => {
- onboardingPage.skillsInput.focus();
- assert.equal(onboardingPage.skillsInput.inputItems(0).text, 'Ruby');
- onboardingPage.skillsInput.inputItems(0).click();
+ onboardingPage.skillsTypeahead.focus();
+ assert.equal(onboardingPage.skillsTypeahead.inputItems(0).text, 'Ruby');
+ onboardingPage.skillsTypeahead.inputItems(0).click();
});
andThen(() => {
@@ -112,13 +112,13 @@ test('A user can onboard as expected', function(assert) {
andThen(() => {
assert.equal(onboardingPage.userSkillsList().count, 0);
- onboardingPage.skillsInput.fillIn('r');
+ onboardingPage.skillsTypeahead.fillIn('r');
});
andThen(() => {
- onboardingPage.skillsInput.focus();
- assert.equal(onboardingPage.skillsInput.inputItems(0).text, 'Ruby');
- onboardingPage.skillsInput.inputItems(0).click();
+ onboardingPage.skillsTypeahead.focus();
+ assert.equal(onboardingPage.skillsTypeahead.inputItems(0).text, 'Ruby');
+ onboardingPage.skillsTypeahead.inputItems(0).click();
});
andThen(() => {
diff --git a/tests/acceptance/project-settings-test.js b/tests/acceptance/project-settings-test.js
index a31162dda..d80dc5ee2 100644
--- a/tests/acceptance/project-settings-test.js
+++ b/tests/acceptance/project-settings-test.js
@@ -120,14 +120,14 @@ test("it allows editing of project's skills", function(assert) {
});
andThen(() => {
- projectSettingsPage.skillsInput.fillIn('ru');
+ projectSettingsPage.skillsTypeahead.fillIn('ru');
});
andThen(() => {
assert.equal(currentURL(), `${project.organization.slug}/${project.slug}/settings/profile`);
- projectSettingsPage.skillsInput.focus();
- assert.equal(projectSettingsPage.skillsInput.inputItems(0).text, 'Ruby');
- projectSettingsPage.skillsInput.inputItems(0).click();
+ projectSettingsPage.skillsTypeahead.focus();
+ assert.equal(projectSettingsPage.skillsTypeahead.inputItems(0).text, 'Ruby');
+ projectSettingsPage.skillsTypeahead.inputItems(0).click();
});
andThen(() => {
diff --git a/tests/integration/components/skills-input-item-test.js b/tests/integration/components/skills-typeahead-result-test.js
similarity index 84%
rename from tests/integration/components/skills-input-item-test.js
rename to tests/integration/components/skills-typeahead-result-test.js
index 9b186458d..abf17bbc0 100644
--- a/tests/integration/components/skills-input-item-test.js
+++ b/tests/integration/components/skills-typeahead-result-test.js
@@ -2,11 +2,11 @@ import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import Ember from 'ember';
import PageObject from 'ember-cli-page-object';
-import skillsInputItemComponent from '../../pages/components/skills-input-item';
+import skillsTypeaheadResultComponent from '../../pages/components/skills-typeahead-result';
const { Object, set } = Ember;
-let page = PageObject.create(skillsInputItemComponent);
+let page = PageObject.create(skillsTypeaheadResultComponent);
let skill = Object.create({
selected: true,
@@ -24,7 +24,7 @@ let userSkillsList = {
}
};
-moduleForComponent('skills-input-item', 'Integration | Component | skills input item', {
+moduleForComponent('skills-typeahead-result', 'Integration | Component | skills input item', {
integration: true,
beforeEach() {
this.set('userSkillsList', userSkillsList);
@@ -44,7 +44,7 @@ test('it renders as selected with the highlighted string', function(assert) {
set(this, 'query', query);
page.render(hbs`
- {{skills-input-item
+ {{skills-typeahead-result
query=query
skill=skill
skillsList=userSkillsList
@@ -68,7 +68,7 @@ test('it sends the hover action on mouseEnter', function(assert) {
assert.deepEqual(skill, hoveredSkill);
});
page.render(hbs`
- {{skills-input-item
+ {{skills-typeahead-result
hover="hover"
query=query
skill=skill
@@ -89,7 +89,7 @@ test('it sends the selectSkill action on mouseDown', function(assert) {
});
page.render(hbs`
- {{skills-input-item
+ {{skills-typeahead-result
hover="hover"
query=query
selectSkill=selectSkill
diff --git a/tests/integration/components/skills-input-test.js b/tests/integration/components/skills-typeahead-test.js
similarity index 80%
rename from tests/integration/components/skills-input-test.js
rename to tests/integration/components/skills-typeahead-test.js
index 1071ca02f..2a62a4c3c 100644
--- a/tests/integration/components/skills-input-test.js
+++ b/tests/integration/components/skills-typeahead-test.js
@@ -3,7 +3,7 @@ import hbs from 'htmlbars-inline-precompile';
import Ember from 'ember';
import stubService from 'code-corps-ember/tests/helpers/stub-service';
import PageObject from 'ember-cli-page-object';
-import skillsInputComponent from '../../pages/components/skills-input';
+import skillsTypeaheadComponent from '../../pages/components/skills-typeahead';
import wait from 'ember-test-helpers/wait';
const {
@@ -12,7 +12,7 @@ const {
set
} = Ember;
-let page = PageObject.create(skillsInputComponent);
+let page = PageObject.create(skillsTypeaheadComponent);
let skills = [
Object.create({ title: 'Ruby' }),
@@ -44,7 +44,7 @@ function setHandlers(context, { selectHandler = function() {} } = {}) {
context.set('selectHandler', selectHandler);
}
-moduleForComponent('skills-input', 'Integration | Component | skills input', {
+moduleForComponent('skills-typeahead', 'Integration | Component | skills input', {
integration: true,
beforeEach() {
stubService(this, 'store', mockStore);
@@ -59,7 +59,7 @@ moduleForComponent('skills-input', 'Integration | Component | skills input', {
test('it does nothing when pressing a random key', function(assert) {
assert.expect(1);
- page.render(hbs`{{skills-input selectSkill=(action selectHandler) skillsList=mockListService}}`);
+ page.render(hbs`{{skills-typeahead selectSkill=(action selectHandler) skillsList=mockListService}}`);
page.pressRKey();
assert.equal(page.inputValue, '');
});
@@ -68,7 +68,7 @@ test('it fetches results when changing the input', function(assert) {
let done = assert.async();
assert.expect(5);
- page.render(hbs`{{skills-input selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
+ page.render(hbs`{{skills-typeahead selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
wait().then(() => {
set(this, 'query', 'ruby ra');
@@ -91,7 +91,7 @@ test('it changes the selection when arrowing up or down', function(assert) {
let done = assert.async();
assert.expect(10);
- page.render(hbs`{{skills-input selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
+ page.render(hbs`{{skills-typeahead selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
wait().then(() => {
set(this, 'query', 'ruby ra');
@@ -125,7 +125,7 @@ test('it hides and clears input when hitting esc key', function(assert) {
let done = assert.async();
assert.expect(3);
- page.render(hbs`{{skills-input selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
+ page.render(hbs`{{skills-typeahead selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
wait().then(() => {
set(this, 'query', 'ruby ra');
@@ -146,7 +146,7 @@ test('it changes the selection when hovering', function(assert) {
let done = assert.async();
assert.expect(4);
- page.render(hbs`{{skills-input selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
+ page.render(hbs`{{skills-typeahead selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
wait().then(() => {
set(this, 'query', 'ruby ra');
@@ -167,7 +167,7 @@ test('it selects the skill when hitting enter', function(assert) {
let done = assert.async();
assert.expect(2);
- page.render(hbs`{{skills-input selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
+ page.render(hbs`{{skills-typeahead selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
wait().then(() => {
set(this, 'query', 'ruby ra');
@@ -185,7 +185,7 @@ test('it selects the skill when hitting comma', function(assert) {
let done = assert.async();
assert.expect(2);
- page.render(hbs`{{skills-input selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
+ page.render(hbs`{{skills-typeahead selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
wait().then(() => {
set(this, 'query', 'ruby ra');
@@ -202,7 +202,7 @@ test('it selects the skill when clicking it', function(assert) {
let done = assert.async();
assert.expect(2);
- page.render(hbs`{{skills-input selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
+ page.render(hbs`{{skills-typeahead selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
wait().then(() => {
set(this, 'query', 'ruby ra');
@@ -225,7 +225,7 @@ test('it does nothing when there are no results', function(assert) {
};
set(this, 'store.query', query);
- page.render(hbs`{{skills-input selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
+ page.render(hbs`{{skills-typeahead selectSkill=(action selectHandler) query=query skillsList=mockListService}}`);
wait().then(() => {
set(this, 'query', 'ruby ra');
diff --git a/tests/pages/components/skills-input-item.js b/tests/pages/components/skills-typeahead-result.js
similarity index 100%
rename from tests/pages/components/skills-input-item.js
rename to tests/pages/components/skills-typeahead-result.js
diff --git a/tests/pages/components/skills-input.js b/tests/pages/components/skills-typeahead.js
similarity index 88%
rename from tests/pages/components/skills-input.js
rename to tests/pages/components/skills-typeahead.js
index 2dd81c38a..03ba8652d 100644
--- a/tests/pages/components/skills-input.js
+++ b/tests/pages/components/skills-typeahead.js
@@ -1,10 +1,10 @@
import {
collection, fillable, isVisible, isHidden, triggerable, value
} from 'ember-cli-page-object';
-import skillsInputItem from './skills-input-item';
+import skillsTypeaheadResult from './skills-typeahead-result';
export default {
- scope: '.skills-input',
+ scope: '.skills-typeahead',
fillIn: fillable('input'),
focus: triggerable('focus', 'input'),
@@ -60,7 +60,7 @@ export default {
}),
inputItems: collection({
- item: skillsInputItem,
- itemScope: skillsInputItem.scope
+ item: skillsTypeaheadResult,
+ itemScope: skillsTypeaheadResult.scope
})
};
diff --git a/tests/pages/onboarding.js b/tests/pages/onboarding.js
index d8ccfc98c..a53b309ba 100644
--- a/tests/pages/onboarding.js
+++ b/tests/pages/onboarding.js
@@ -9,7 +9,7 @@ import {
triggerable,
visitable
} from 'ember-cli-page-object';
-import skillsInput from './components/skills-input';
+import skillsTypeahead from './components/skills-typeahead';
import navMenu from './components/navigation-menu';
export default create({
@@ -58,8 +58,8 @@ export default create({
}
}),
- // select and manipulate .skills-input and various site-chrome nodes to
+ // select and manipulate .skills-typeahead and various site-chrome nodes to
// this page
- skillsInput,
+ skillsTypeahead,
navMenu
});
diff --git a/tests/pages/project/settings/profile.js b/tests/pages/project/settings/profile.js
index 79bea15b7..dca2ff575 100644
--- a/tests/pages/project/settings/profile.js
+++ b/tests/pages/project/settings/profile.js
@@ -6,7 +6,7 @@ import {
visitable
} from 'ember-cli-page-object';
import projectSettingsForm from '../../components/project-settings-form';
-import skillsInput from '../../components/skills-input';
+import skillsTypeahead from '../../components/skills-typeahead';
export default create({
visit: visitable(':organization/:project/settings/profile'),
@@ -26,5 +26,5 @@ export default create({
},
projectSettingsForm,
- skillsInput
+ skillsTypeahead
});
diff --git a/tests/unit/utils/skills-list-test.js b/tests/unit/utils/records-list-test.js
similarity index 77%
rename from tests/unit/utils/skills-list-test.js
rename to tests/unit/utils/records-list-test.js
index 812ba7f4c..c579ebe51 100644
--- a/tests/unit/utils/skills-list-test.js
+++ b/tests/unit/utils/records-list-test.js
@@ -1,5 +1,5 @@
import Ember from 'ember';
-import skillsList from 'code-corps-ember/utils/skills-list';
+import recordsList from 'code-corps-ember/utils/records-list';
import { module, test } from 'qunit';
const { isEmpty, Object } = Ember;
@@ -34,30 +34,32 @@ let skill = Object.create({
belongsTo(relationshipName) {
return { id: `${relationshipName}-1` };
},
- constructor: {
- modelName: 'skill'
+ content: {
+ constructor: {
+ modelName: 'skill'
+ }
},
id: 'skill-1'
});
test('find returns a match correctly', function(assert) {
let projectSkills = [projectSkill];
- let result = skillsList.find(projectSkills, skill, project);
+ let result = recordsList.find(projectSkills, skill, project);
assert.equal(projectSkill, result);
});
test('find returns no match correctly', function(assert) {
- let result = skillsList.find([], skill, project);
+ let result = recordsList.find([], skill, project);
assert.ok(isEmpty(result));
});
test('contains returns true when there is a match', function(assert) {
let projectSkills = [projectSkill];
- let result = skillsList.contains(projectSkills, skill);
+ let result = recordsList.contains(projectSkills, skill);
assert.ok(result);
});
test('contains returns false when there is no match', function(assert) {
- let result = skillsList.contains([], skill);
+ let result = recordsList.contains([], skill);
assert.notOk(result);
});