Skip to content

Commit

Permalink
fix(form): fix premature access to validators which are not yet fetched
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonas Metzener authored and czosel committed Jul 23, 2019
1 parent afb894f commit df6a6e6
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 47 deletions.
12 changes: 6 additions & 6 deletions addon/lib/field.js
Expand Up @@ -442,12 +442,12 @@ export default Base.extend({
* @return {Object|Boolean} Returns an object if invalid or true if valid
* @internal
*/
_validateTextQuestion() {
async _validateTextQuestion() {
return [
...this.validator.validate(
...(await this.validator.validate(
this.get("answer.value"),
this.getWithDefault("question.meta.formatValidators", [])
),
)),
validate("length", this.get("answer.value"), {
max: this.get("question.textMaxLength") || Number.POSITIVE_INFINITY
})
Expand All @@ -462,12 +462,12 @@ export default Base.extend({
* @return {Object|Boolean} Returns an object if invalid or true if valid
* @internal
*/
_validateTextareaQuestion() {
async _validateTextareaQuestion() {
return [
...this.validator.validate(
...(await this.validator.validate(
this.get("answer.value"),
this.getWithDefault("question.meta.formatValidators", [])
),
)),
validate("length", this.get("answer.value"), {
max: this.get("question.textareaMaxLength") || Number.POSITIVE_INFINITY
})
Expand Down
35 changes: 12 additions & 23 deletions addon/services/validator.js
@@ -1,32 +1,28 @@
import Service from "@ember/service";
import { task } from "ember-concurrency";
import allFormatValidatorsQuery from "ember-caluma/gql/queries/all-format-validators";
import { computed } from "@ember/object";
import { assert } from "@ember/debug";
import { ObjectQueryManager } from "ember-apollo-client";
import { next } from "@ember/runloop";

export default Service.extend(ObjectQueryManager, {
init() {
this._super(...arguments);

next(this._fetchValidators, "perform");
},

/**
* Tests a value against one or multiple regular expressions.
*
* ```js
* this.validator.validate("foo@example.com", ["email", "lowercase"]);
* await this.validator.validate("foo@example.com", ["email", "lowercase"]);
* ```
*
* @param {String} value The value to be tested.
* @param {String[]} slugs A list of tests (via slug) to run.
* @return {RSVP.Promise}
*/
validate(value, slugs) {
async validate(value, slugs) {
const validators =
this.get("validators.lastSuccessful.value") ||
(await this.validators.perform());

return slugs.map(slug => {
const validator = this.validators.find(
validator => validator.slug === slug
);
const validator = validators.find(validator => validator.slug === slug);

assert(`No validator found with the slug "${slug}".`, validator);

Expand All @@ -41,20 +37,13 @@ export default Service.extend(ObjectQueryManager, {
});
},

_fetchValidators: task(function*() {
return yield this.apollo.query(
validators: task(function*() {
const raw = yield this.apollo.query(
{ query: allFormatValidatorsQuery },
"allFormatValidators.edges"
);
}),

validators: computed("_fetchValidators.lastSuccessful.value.[]", function() {
const rawValidators = this.getWithDefault(
"_fetchValidators.lastSuccessful.value",
[]
);

return rawValidators.map(rawValidator => {
return raw.map(rawValidator => {
return {
slug: rawValidator.node.slug,
regex: new RegExp(rawValidator.node.regex),
Expand Down
2 changes: 1 addition & 1 deletion tests/helpers/validator-service-stub.js
@@ -1,7 +1,7 @@
import Service from "@ember/service";

export default Service.extend({
validate() {
async validate() {
return [true];
}
});
11 changes: 5 additions & 6 deletions tests/integration/components/cf-field-test.js
Expand Up @@ -3,15 +3,17 @@ import { setupRenderingTest } from "ember-qunit";
import { render, fillIn } from "@ember/test-helpers";
import hbs from "htmlbars-inline-precompile";
import Document from "ember-caluma/lib/document";
import { settled } from "@ember/test-helpers";
import setupMirage from "ember-cli-mirage/test-support/setup-mirage";

module("Integration | Component | cf-field", function(hooks) {
setupRenderingTest(hooks);
setupMirage(hooks);

hooks.beforeEach(function() {
this.server.create("format-validator", { slug: "email", regex: "/@/" });
this.validator = this.server.create("format-validator", {
slug: "email",
regex: "/@/"
});

const form = {
__typename: "Form",
Expand Down Expand Up @@ -120,15 +122,12 @@ module("Integration | Component | cf-field", function(hooks) {

test("it shows error message", async function(assert) {
assert.expect(1);
let service = this.owner.lookup("service:validator");
await settled();
let error = service.validators.find(i => i.slug === "email").errorMsg;

await render(hbs`{{cf-field field=errorField}}`);

await fillIn("input", "Test");

assert.dom("span.validation-errors").hasText(error);
assert.dom("span.validation-errors").hasText(this.validator.errorMsg);
});

test("it saves the valid email address", async function(assert) {
Expand Down
16 changes: 5 additions & 11 deletions tests/unit/services/validator-test.js
@@ -1,7 +1,6 @@
import { module, test } from "qunit";
import { setupTest } from "ember-qunit";
import { setupMirage } from "ember-cli-mirage/test-support";
import { settled } from "@ember/test-helpers";

module("Unit | Service | validator", function(hooks) {
setupTest(hooks);
Expand All @@ -11,18 +10,13 @@ module("Unit | Service | validator", function(hooks) {
this.server.create("format-validator", { slug: "email", regex: ".+" });
});

test("it exists", function(assert) {
assert.expect(1);
let service = this.owner.lookup("service:validator");
assert.ok(service);
});

test("slugs are in a string not in an array", async function(assert) {
assert.expect(1);
this.server.logging = true;

let service = this.owner.lookup("service:validator");
await settled();
let result = service.validate("test@test.com", ["email"]);
assert.deepEqual(result, [true]);

assert.deepEqual(await service.validate("test@test.com", ["email"]), [
true
]);
});
});

0 comments on commit df6a6e6

Please sign in to comment.