@projectcaluma/ember-testing 10.2.0-beta.1 → 11.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +1101 -0
  2. package/addon/mirage-graphql/deserialize.js +13 -0
  3. package/addon/mirage-graphql/filters/answer.js +1 -1
  4. package/addon/mirage-graphql/filters/base.js +19 -22
  5. package/addon/mirage-graphql/filters/form.js +5 -1
  6. package/addon/mirage-graphql/filters/index.js +17 -0
  7. package/addon/mirage-graphql/filters/question.js +1 -1
  8. package/addon/mirage-graphql/filters/work-item.js +1 -1
  9. package/addon/mirage-graphql/index.js +59 -63
  10. package/addon/mirage-graphql/mocks/answer.js +8 -14
  11. package/addon/mirage-graphql/mocks/base.js +9 -11
  12. package/addon/mirage-graphql/mocks/form.js +2 -2
  13. package/addon/mirage-graphql/mocks/index.js +17 -0
  14. package/addon/mirage-graphql/mocks/question.js +5 -5
  15. package/addon/mirage-graphql/mocks/work-item.js +55 -5
  16. package/addon/mirage-graphql/register.js +20 -0
  17. package/addon/mirage-graphql/schema.graphql +757 -1873
  18. package/addon/mirage-graphql/serialize.js +14 -0
  19. package/addon/scenarios/distribution.js +136 -31
  20. package/addon-mirage-support/factories/answer.js +17 -18
  21. package/addon-mirage-support/factories/case.js +3 -3
  22. package/addon-mirage-support/factories/document.js +4 -2
  23. package/addon-mirage-support/factories/file.js +3 -3
  24. package/addon-mirage-support/factories/form.js +3 -2
  25. package/addon-mirage-support/factories/format-validator.js +2 -2
  26. package/addon-mirage-support/factories/option.js +1 -1
  27. package/addon-mirage-support/factories/question.js +2 -2
  28. package/addon-mirage-support/factories/task.js +2 -2
  29. package/addon-mirage-support/factories/work-item.js +3 -3
  30. package/addon-mirage-support/factories/workflow.js +1 -1
  31. package/addon-mirage-support/models/answer.js +1 -1
  32. package/addon-mirage-support/models/case.js +1 -1
  33. package/addon-mirage-support/models/document.js +1 -1
  34. package/addon-mirage-support/models/file.js +1 -1
  35. package/addon-mirage-support/models/form.js +1 -1
  36. package/addon-mirage-support/models/format-validator.js +1 -1
  37. package/addon-mirage-support/models/option.js +1 -1
  38. package/addon-mirage-support/models/question.js +2 -1
  39. package/addon-mirage-support/models/task.js +1 -1
  40. package/addon-mirage-support/models/work-item.js +1 -1
  41. package/addon-mirage-support/models/workflow.js +1 -1
  42. package/blueprints/@projectcaluma/ember-testing/index.js +1 -4
  43. package/package.json +16 -15
  44. package/addon/mirage-graphql/handler.js +0 -60
@@ -0,0 +1,13 @@
1
+ export default function deserialize(serialized) {
2
+ let decodedId = serialized.id;
3
+
4
+ try {
5
+ decodedId = atob(serialized.id).split(":")[1] || serialized.id;
6
+ } catch (e) {
7
+ // This will happen if the ID is not a relay ID (Type plus ID base64
8
+ // encoded) but just the raw ID. The deserialize function needs to be able
9
+ // to handle both
10
+ }
11
+
12
+ return { ...serialized, ...(decodedId ? { id: decodedId } : {}) };
13
+ }
@@ -1,6 +1,6 @@
1
1
  import BaseFilter from "@projectcaluma/ember-testing/mirage-graphql/filters/base";
2
2
 
3
- export default class extends BaseFilter {
3
+ export default class AnswerFilter extends BaseFilter {
4
4
  questions(records, value, { invert = false }) {
5
5
  return records.filter(
6
6
  (record) => invert !== value.includes(record.questionId)
@@ -1,35 +1,28 @@
1
1
  import { camelize } from "@ember/string";
2
2
 
3
- export default class {
3
+ export default class BaseFilter {
4
4
  constructor(type) {
5
5
  this.type = type;
6
6
  }
7
7
 
8
8
  _getFilterFns(rawFilters) {
9
- const filters = Array.isArray(rawFilters)
10
- ? // new format
11
- rawFilters
12
- .filter((filter) => Object.keys(filter).length !== 0) // filter out empty filters
13
- .map((filter) => {
14
- const entries = Object.entries(filter);
15
- const key = entries[0][0];
16
- const value = entries[0][1];
17
- const options = entries
18
- .slice(1)
19
- .reduce((opts, [k, v]) => ({ ...opts, [k]: v }), {});
9
+ const filters = rawFilters
10
+ .filter((filter) => Object.keys(filter).length !== 0) // filter out empty filters
11
+ .map((filter) => {
12
+ const entries = Object.entries(filter);
13
+ const key = entries[0][0];
14
+ const value = entries[0][1];
15
+ const options = entries
16
+ .slice(1)
17
+ .reduce((opts, [k, v]) => ({ ...opts, [k]: v }), {});
20
18
 
21
- return { key, value, options };
22
- })
23
- : // old format
24
- Object.entries(rawFilters).map(([key, value]) => ({
25
- key,
26
- value,
27
- }));
19
+ return { key, value, options };
20
+ });
28
21
 
29
22
  return filters.map(({ key, value, options = {} }) => {
30
23
  const fn = this[key];
31
24
 
32
- return typeof fn === "function"
25
+ return typeof fn === "function" && ![null, undefined].includes(value)
33
26
  ? (records) => fn.call(this, records, value, options)
34
27
  : (records) => records;
35
28
  });
@@ -53,7 +46,7 @@ export default class {
53
46
  }
54
47
 
55
48
  filter(records, filters) {
56
- return this._getFilterFns(filters.filter ?? filters).reduce(
49
+ return this._getFilterFns(filters?.filter ?? []).reduce(
57
50
  (recs, fn) => fn(recs),
58
51
  this.sort(records, filters?.order)
59
52
  );
@@ -64,7 +57,11 @@ export default class {
64
57
  }
65
58
 
66
59
  slug(records, value) {
67
- return records.filter(({ slug }) => slug === value);
60
+ return this.slugs(records, [value]);
61
+ }
62
+
63
+ slugs(records, values) {
64
+ return records.filter(({ slug }) => values.includes(slug));
68
65
  }
69
66
 
70
67
  id(records, value) {
@@ -1,10 +1,14 @@
1
1
  import BaseFilter from "@projectcaluma/ember-testing/mirage-graphql/filters/base";
2
2
 
3
- export default class extends BaseFilter {
3
+ export default class FormFilter extends BaseFilter {
4
4
  isArchived(records, value) {
5
5
  return records.filter(({ isArchived }) => isArchived === value);
6
6
  }
7
7
 
8
+ isPublished(records, value) {
9
+ return records.filter(({ isPublished }) => isPublished === value);
10
+ }
11
+
8
12
  search(records, value) {
9
13
  const re = new RegExp(`.*${value}.*`, "i");
10
14
 
@@ -0,0 +1,17 @@
1
+ import AnswerFilter from "@projectcaluma/ember-testing/mirage-graphql/filters/answer";
2
+ import BaseFilter from "@projectcaluma/ember-testing/mirage-graphql/filters/base";
3
+ import FormFilter from "@projectcaluma/ember-testing/mirage-graphql/filters/form";
4
+ import QuestionFilter from "@projectcaluma/ember-testing/mirage-graphql/filters/question";
5
+ import WorkItemFilter from "@projectcaluma/ember-testing/mirage-graphql/filters/work-item";
6
+
7
+ const FILTER_MAPPING = {
8
+ Answer: AnswerFilter,
9
+ Form: FormFilter,
10
+ Question: QuestionFilter,
11
+ WorkItem: WorkItemFilter,
12
+ };
13
+
14
+ export default function createFilter(type, ...args) {
15
+ const FilterClass = FILTER_MAPPING[type] ?? BaseFilter;
16
+ return new FilterClass(type, ...args);
17
+ }
@@ -1,6 +1,6 @@
1
1
  import BaseFilter from "@projectcaluma/ember-testing/mirage-graphql/filters/base";
2
2
 
3
- export default class extends BaseFilter {
3
+ export default class QuestionFilter extends BaseFilter {
4
4
  isArchived(records, value) {
5
5
  return records.filter(({ isArchived }) => isArchived === value);
6
6
  }
@@ -1,6 +1,6 @@
1
1
  import BaseFilter from "@projectcaluma/ember-testing/mirage-graphql/filters/base";
2
2
 
3
- export default class extends BaseFilter {
3
+ export default class WorkItemFilter extends BaseFilter {
4
4
  status(records, value, { invert = false }) {
5
5
  return records.filter(({ status }) => invert !== (status === value));
6
6
  }
@@ -1,64 +1,60 @@
1
- import { dasherize, classify } from "@ember/string";
2
- import require from "require";
3
-
4
- const importTypeOrBase = (path, type) => {
5
- try {
6
- return require(`${path}/${dasherize(type)}`).default;
7
- } catch (e) {
8
- return require(`${path}/base`).default;
9
- }
10
- };
11
-
12
- export const register = (tpl) => (target, name, descriptor) => {
13
- if (descriptor.value.__isHandler) {
14
- descriptor.value.__handlerFor.push(tpl);
15
- return descriptor;
16
- }
17
-
18
- descriptor.writable = false;
19
- descriptor.enumerable = true;
20
-
21
- descriptor.value = {
22
- __isHandler: true,
23
- // Mocks can have multiple handlers per type.
24
- __handlerFor: [tpl],
25
- fn: descriptor.value,
26
- };
27
-
28
- return descriptor;
29
- };
30
-
31
- export const serialize = (deserialized = {}, type) => {
32
- const __typename = [deserialized.type?.toLowerCase(), type]
33
- .filter(Boolean)
34
- .map(classify)
35
- .join("");
36
-
37
- return {
38
- ...deserialized,
39
- id: btoa(`${__typename}:${deserialized.id}`),
40
- __typename,
1
+ import { classify } from "@ember/string";
2
+ import { singularize } from "ember-inflector";
3
+ import { graphql } from "graphql";
4
+ import {
5
+ GraphQLDate as Date,
6
+ GraphQLDateTime as DateTime,
7
+ } from "graphql-iso-date";
8
+ import { addMockFunctionsToSchema, makeExecutableSchema } from "graphql-tools";
9
+
10
+ import createMock from "@projectcaluma/ember-testing/mirage-graphql/mocks";
11
+ import typeDefs from "@projectcaluma/ember-testing/mirage-graphql/schema.graphql";
12
+
13
+ export default function createGraphqlHandler(server) {
14
+ return function graphqlHandler({ db }, request) {
15
+ const mocks = db._collections.reduce((m, { name }) => {
16
+ const cls = classify(singularize(name));
17
+ const mock = createMock(cls, server);
18
+
19
+ return { ...m, ...mock.getHandlers() };
20
+ }, {});
21
+
22
+ const schema = makeExecutableSchema({
23
+ typeDefs,
24
+ resolvers: {
25
+ Date,
26
+ DateTime,
27
+ GenericScalar: {
28
+ serialize(value) {
29
+ return typeof value === "string" ? JSON.parse(value) : value;
30
+ },
31
+ },
32
+ },
33
+ resolverValidationOptions: { requireResolversForResolveType: false },
34
+ });
35
+
36
+ const { query, variables } = JSON.parse(request.requestBody);
37
+
38
+ addMockFunctionsToSchema({
39
+ schema,
40
+ mocks: {
41
+ ...mocks,
42
+ JSONString: () => JSON.stringify({}),
43
+ GenericScalar: () => ({}),
44
+ Node: (_, { id }) => ({ __typename: atob(id).split(":")[0] }),
45
+ SelectedOption: ({ value }) => {
46
+ const option = server.schema.options.findBy({ slug: value });
47
+
48
+ return {
49
+ slug: value,
50
+ label: option.label,
51
+ __typename: "SelectedOption",
52
+ };
53
+ },
54
+ },
55
+ preserveResolvers: false,
56
+ });
57
+
58
+ return graphql(schema, query, null, null, variables);
41
59
  };
42
- };
43
-
44
- export const deserialize = (serialized) => {
45
- let decodedId = serialized.id;
46
-
47
- try {
48
- decodedId = atob(serialized.id).split(":")[1] || serialized.id;
49
- } catch (e) {
50
- // this is expected most times
51
- }
52
-
53
- return { ...serialized, ...(decodedId ? { id: decodedId } : {}) };
54
- };
55
-
56
- export const Filter = function (type, ...args) {
57
- return new (importTypeOrBase("./filters", type))(type, ...args);
58
- };
59
-
60
- export const Mock = function (type, ...args) {
61
- return new (importTypeOrBase("./mocks", type))(type, ...args);
62
- };
63
-
64
- export { default } from "./handler";
60
+ }
@@ -1,9 +1,9 @@
1
- import moment from "moment";
1
+ import { DateTime } from "luxon";
2
2
 
3
- import { register } from "@projectcaluma/ember-testing/mirage-graphql";
4
3
  import BaseMock from "@projectcaluma/ember-testing/mirage-graphql/mocks/base";
4
+ import register from "@projectcaluma/ember-testing/mirage-graphql/register";
5
5
 
6
- export default class extends BaseMock {
6
+ export default class AnswerMock extends BaseMock {
7
7
  _handleSaveDocumentAnswer(
8
8
  _,
9
9
  { question: questionId, document: documentId, value, type }
@@ -61,12 +61,12 @@ export default class extends BaseMock {
61
61
  });
62
62
  }
63
63
 
64
- @register("SaveDocumentFileAnswerPayload")
65
- handleSaveFileAnswer(_, { input }) {
64
+ @register("SaveDocumentFilesAnswerPayload")
65
+ handleSaveFilesAnswer(_, { input }) {
66
66
  return this._handleSaveDocumentAnswer(_, {
67
67
  ...input,
68
- value: input.value ? { metadata: { object_name: input.value } } : null,
69
- type: "FILE",
68
+ value: input.value ? [...input.value] : [],
69
+ type: "FILES",
70
70
  });
71
71
  }
72
72
 
@@ -74,13 +74,7 @@ export default class extends BaseMock {
74
74
  @register("SaveDefaultDateAnswerPayload")
75
75
  handleSaveDateAnswer(_, { input }) {
76
76
  const date = input.value;
77
- const value = date
78
- ? moment({
79
- day: date.getUTCDate(),
80
- month: date.getUTCMonth(),
81
- year: date.getUTCFullYear(),
82
- }).format(moment.HTML5_FMT.DATE)
83
- : null;
77
+ const value = date ? DateTime.fromJSDate(date).toISODate() : null;
84
78
 
85
79
  return this._handleSaveDocumentAnswer(_, {
86
80
  ...input,
@@ -1,18 +1,16 @@
1
1
  import { camelize, dasherize, classify } from "@ember/string";
2
+ import { faker } from "@faker-js/faker";
2
3
  import { singularize, pluralize } from "ember-inflector";
3
- import faker from "faker";
4
4
  import { MockList } from "graphql-tools";
5
5
 
6
- import {
7
- Filter,
8
- register,
9
- serialize,
10
- deserialize,
11
- } from "@projectcaluma/ember-testing/mirage-graphql";
6
+ import deserialize from "@projectcaluma/ember-testing/mirage-graphql/deserialize";
7
+ import createFilter from "@projectcaluma/ember-testing/mirage-graphql/filters";
8
+ import register from "@projectcaluma/ember-testing/mirage-graphql/register";
9
+ import serialize from "@projectcaluma/ember-testing/mirage-graphql/serialize";
12
10
 
13
11
  export const ANSWER_TYPES = [
14
12
  "DATE",
15
- "FILE",
13
+ "FILES",
16
14
  "FLOAT",
17
15
  "INTEGER",
18
16
  "LIST",
@@ -27,7 +25,7 @@ export const QUESTION_TYPES = [
27
25
  "DATE",
28
26
  "DYNAMIC_CHOICE",
29
27
  "DYNAMIC_MULTIPLE_CHOICE",
30
- "FILE",
28
+ "FILES",
31
29
  "FLOAT",
32
30
  "FORM",
33
31
  "INTEGER",
@@ -50,13 +48,13 @@ export const TYPE_MAPPING = {
50
48
  Task: TASK_TYPES,
51
49
  };
52
50
 
53
- export default class {
51
+ export default class BaseMock {
54
52
  constructor(type, server) {
55
53
  this.type = type;
56
54
  this.server = server;
57
55
  this.schema = server.schema;
58
56
 
59
- this.filter = new Filter(type);
57
+ this.filter = createFilter(type);
60
58
  }
61
59
 
62
60
  get collection() {
@@ -1,7 +1,7 @@
1
- import { register } from "@projectcaluma/ember-testing/mirage-graphql";
2
1
  import BaseMock from "@projectcaluma/ember-testing/mirage-graphql/mocks/base";
2
+ import register from "@projectcaluma/ember-testing/mirage-graphql/register";
3
3
 
4
- export default class extends BaseMock {
4
+ export default class FormMock extends BaseMock {
5
5
  @register("ReorderFormQuestionsPayload")
6
6
  handleReorderFormQuestions(_, { input }) {
7
7
  return this.handleSavePayload.fn.call(this, _, {
@@ -0,0 +1,17 @@
1
+ import AnswerMock from "@projectcaluma/ember-testing/mirage-graphql/mocks/answer";
2
+ import BaseMock from "@projectcaluma/ember-testing/mirage-graphql/mocks/base";
3
+ import FormMock from "@projectcaluma/ember-testing/mirage-graphql/mocks/form";
4
+ import QuestionMock from "@projectcaluma/ember-testing/mirage-graphql/mocks/question";
5
+ import WorkItemMock from "@projectcaluma/ember-testing/mirage-graphql/mocks/work-item";
6
+
7
+ const MOCK_MAPPING = {
8
+ Answer: AnswerMock,
9
+ Form: FormMock,
10
+ Question: QuestionMock,
11
+ WorkItem: WorkItemMock,
12
+ };
13
+
14
+ export default function createMock(type, ...args) {
15
+ const MockClass = MOCK_MAPPING[type] ?? BaseMock;
16
+ return new MockClass(type, ...args);
17
+ }
@@ -1,7 +1,7 @@
1
- import { register } from "@projectcaluma/ember-testing/mirage-graphql";
2
1
  import BaseMock from "@projectcaluma/ember-testing/mirage-graphql/mocks/base";
2
+ import register from "@projectcaluma/ember-testing/mirage-graphql/register";
3
3
 
4
- export default class extends BaseMock {
4
+ export default class QuestionMock extends BaseMock {
5
5
  @register("SaveTextQuestionPayload")
6
6
  handleSaveTextQuestion(_, { input }) {
7
7
  return this.handleSavePayload.fn.call(this, _, {
@@ -92,10 +92,10 @@ export default class extends BaseMock {
92
92
  });
93
93
  }
94
94
 
95
- @register("SaveFileQuestionPayload")
96
- handleSaveFileQuestion(_, { input }) {
95
+ @register("SaveFilesQuestionPayload")
96
+ handleSaveFilesQuestion(_, { input }) {
97
97
  return this.handleSavePayload.fn.call(this, _, {
98
- input: { ...input, type: "FILE" },
98
+ input: { ...input, type: "FILES" },
99
99
  });
100
100
  }
101
101
  }
@@ -1,10 +1,11 @@
1
- import {
2
- register,
3
- deserialize,
4
- } from "@projectcaluma/ember-testing/mirage-graphql";
1
+ import { DateTime } from "luxon";
2
+
3
+ import deserialize from "@projectcaluma/ember-testing/mirage-graphql/deserialize";
5
4
  import BaseMock from "@projectcaluma/ember-testing/mirage-graphql/mocks/base";
5
+ import register from "@projectcaluma/ember-testing/mirage-graphql/register";
6
+ import { createInquiry } from "@projectcaluma/ember-testing/scenarios/distribution";
6
7
 
7
- export default class extends BaseMock {
8
+ export default class WorkItemMock extends BaseMock {
8
9
  @register("ResumeWorkItemPayload")
9
10
  handleResumeWorkItem(_, { input }) {
10
11
  return this.handleSavePayload.fn.call(this, _, {
@@ -19,6 +20,13 @@ export default class extends BaseMock {
19
20
  });
20
21
  }
21
22
 
23
+ @register("CancelWorkItemPayload")
24
+ handleCancelWorkItem(_, { input }) {
25
+ return this.handleSavePayload.fn.call(this, _, {
26
+ input: { id: input.id, status: "CANCELED" },
27
+ });
28
+ }
29
+
22
30
  @register("CompleteWorkItemPayload")
23
31
  handleCompleteWorkItem(_, { input }) {
24
32
  const { id } = deserialize(input);
@@ -63,6 +71,48 @@ export default class extends BaseMock {
63
71
  status: "READY",
64
72
  taskId: "adjust-inquiry-answer",
65
73
  });
74
+ } else if (taskId === "create-inquiry") {
75
+ const { addressed_groups: groups } = JSON.parse(input.context);
76
+
77
+ groups.forEach((group) => {
78
+ createInquiry(
79
+ this.server,
80
+ workItem.case,
81
+ {
82
+ to: { id: group },
83
+ from: { id: workItem.addressedGroups[0] },
84
+ remark: "",
85
+ deadline: DateTime.now().plus({ days: 30 }).toJSDate(),
86
+ },
87
+ {
88
+ createdAt: new Date(),
89
+ }
90
+ );
91
+
92
+ this.server.create("work-item", {
93
+ taskId: "create-inquiry",
94
+ status: "READY",
95
+ addressedGroups: [group],
96
+ });
97
+ });
98
+
99
+ this.server.create("work-item", {
100
+ taskId: "create-inquiry",
101
+ status: "READY",
102
+ addressedGroups: workItem.addressedGroups,
103
+ });
104
+ } else if (taskId === "complete-distribution") {
105
+ this.collection
106
+ .where({ caseId, status: "READY", taskId: "inquiry" })
107
+ .update({ status: "SKIPPED" });
108
+
109
+ this.collection
110
+ .where({ caseId, status: "READY" })
111
+ .update({ status: "CANCELED" });
112
+
113
+ this.collection
114
+ .where({ caseId, status: "SUSPENDED" })
115
+ .update({ status: "CANCELED" });
66
116
  }
67
117
 
68
118
  return this.handleSavePayload.fn.call(this, _, {
@@ -0,0 +1,20 @@
1
+ export default function register(tpl) {
2
+ return function decorate(target, name, descriptor) {
3
+ if (descriptor.value.__isHandler) {
4
+ descriptor.value.__handlerFor.push(tpl);
5
+ return descriptor;
6
+ }
7
+
8
+ descriptor.writable = false;
9
+ descriptor.enumerable = true;
10
+
11
+ descriptor.value = {
12
+ __isHandler: true,
13
+ // Mocks can have multiple handlers per type.
14
+ __handlerFor: [tpl],
15
+ fn: descriptor.value,
16
+ };
17
+
18
+ return descriptor;
19
+ };
20
+ }