1 | import CONFIGURATION_1 from './data/configuration_1.json';
|
2 | import CONFIGURATION_1_OPERATIONS_1 from './data/configuration_1_operations_1.json';
|
3 | import CONFIGURATION_2 from './data/configuration_2.json';
|
4 |
|
5 | import parse from '../src/parse';
|
6 | import semver from 'semver';
|
7 | import craftai, { errors } from '../src';
|
8 |
|
9 | const CONFIGURATION_1_OPERATIONS_1_TO = _.last(CONFIGURATION_1_OPERATIONS_1).timestamp;
|
10 |
|
11 | const CONFIGURATION_2_BATCH_DURATION = CONFIGURATION_2.learning_period * 4;
|
12 | const CONFIGURATION_2_ENUM_VALUES = ['CYAN', 'MAGENTA', 'YELLOW', 'BLACK'];
|
13 |
|
14 | function randomEnumValue() {
|
15 | return CONFIGURATION_2_ENUM_VALUES[_.random(0, CONFIGURATION_2_ENUM_VALUES.length - 1)];
|
16 | }
|
17 |
|
18 | function randomContinuousValue() {
|
19 | return _.random(-12, 12);
|
20 | }
|
21 |
|
22 | const CONFIGURATION_2_OPERATIONS = _.map(_.range(0, 60), (batchOffset) => {
|
23 | return _.map(_.range(0, CONFIGURATION_2_BATCH_DURATION, 1000), (operationOffset) => ({
|
24 | timestamp: batchOffset * CONFIGURATION_2_BATCH_DURATION + operationOffset,
|
25 | context: {
|
26 | e1: randomEnumValue(),
|
27 | e2: randomEnumValue(),
|
28 | e3: randomEnumValue(),
|
29 | e4: randomEnumValue(),
|
30 | c1: randomContinuousValue(),
|
31 | c2: randomContinuousValue(),
|
32 | c3: randomContinuousValue(),
|
33 | c4: randomContinuousValue(),
|
34 | tz: 'CET'
|
35 | }
|
36 | }));
|
37 | });
|
38 |
|
39 | describe('client.getAgentDecisionTree(<agentId>, <timestamp>)', function() {
|
40 | let client;
|
41 | let agent;
|
42 | const agentId = `get_agent_decision_tree_${RUN_ID}`;
|
43 |
|
44 | before(function() {
|
45 | client = craftai(CRAFT_CFG);
|
46 | expect(client).to.be.ok;
|
47 | });
|
48 |
|
49 | beforeEach(function() {
|
50 | return client.deleteAgent(agentId);
|
51 | });
|
52 |
|
53 | afterEach(function() {
|
54 | return client.deleteAgent(agentId);
|
55 | });
|
56 |
|
57 | describe('on an agent with few data', function() {
|
58 | beforeEach(function() {
|
59 | return client.createAgent(CONFIGURATION_1, agentId)
|
60 | .then((createdAgent) => {
|
61 | expect(createdAgent).to.be.ok;
|
62 | agent = createdAgent;
|
63 | return client.addAgentContextOperations(agent.id, CONFIGURATION_1_OPERATIONS_1);
|
64 | });
|
65 | });
|
66 |
|
67 | it('should succeed when using valid parameters', function() {
|
68 | return client.getAgentDecisionTree(agent.id, CONFIGURATION_1_OPERATIONS_1_TO)
|
69 | .then((treeJson) => {
|
70 | expect(treeJson).to.be.ok;
|
71 | const { _version, configuration, trees } = parse(treeJson);
|
72 | expect(trees).to.be.ok;
|
73 | expect(_version).to.be.ok;
|
74 | expect(configuration).to.be.deep.equal(CONFIGURATION_1);
|
75 | });
|
76 | });
|
77 |
|
78 | it('should succeed when passing a version parameters', function() {
|
79 | let version = '1';
|
80 | return client.getAgentDecisionTree(agent.id, CONFIGURATION_1_OPERATIONS_1_TO, version)
|
81 | .then((treeJson) => {
|
82 | expect(treeJson).to.be.ok;
|
83 | const { _version, configuration, trees } = parse(treeJson);
|
84 | expect(trees).to.be.ok;
|
85 | expect(_version).to.be.ok;
|
86 | expect(semver.major(_version)).to.be.equal(parseInt(version));
|
87 | expect(configuration).to.be.deep.equal(CONFIGURATION_1);
|
88 | });
|
89 | });
|
90 |
|
91 | it('should fail with a timeout error when the client side timeout is low', function() {
|
92 | const otherClient = craftai(_.assign({}, CRAFT_CFG, {
|
93 | decisionTreeRetrievalTimeout: 50
|
94 | }));
|
95 | return otherClient.getAgentDecisionTree(agent.id, CONFIGURATION_1_OPERATIONS_1_TO)
|
96 | .then(
|
97 | () => Promise.reject(new Error('Should not be reached')),
|
98 | (err) => {
|
99 | expect(err).to.be.an.instanceof(errors.CraftAiLongRequestTimeOutError);
|
100 | }
|
101 | );
|
102 | });
|
103 | });
|
104 |
|
105 | (DISABLE_LONG_TESTS ? describe.skip : describe)('on an agent with data spanning a looong time', function() {
|
106 | beforeEach(function() {
|
107 | return client.createAgent(CONFIGURATION_2, agentId)
|
108 | .then((createdAgent) => {
|
109 | expect(createdAgent).to.be.ok;
|
110 | agent = createdAgent;
|
111 | return _.reduce(CONFIGURATION_2_OPERATIONS, (p, operations) => {
|
112 | return p.then(() => client.addAgentContextOperations(agent.id, operations));
|
113 | }, Promise.resolve());
|
114 | });
|
115 | });
|
116 |
|
117 | it('should fail with a timeout error when the client side timeout is deactivated', function() {
|
118 | this.timeout(100000);
|
119 | const otherClient = craftai(_.assign({}, CRAFT_CFG, {
|
120 | decisionTreeRetrievalTimeout: false
|
121 | }));
|
122 | const lastOperation = _.last(_.last(CONFIGURATION_2_OPERATIONS));
|
123 | return otherClient.getAgentDecisionTree(agent.id, lastOperation.timestamp)
|
124 | .then(
|
125 | () => Promise.reject(new Error('Should not be reached')),
|
126 | (err) => {
|
127 | expect(err).to.be.an.instanceof(errors.CraftAiLongRequestTimeOutError);
|
128 | }
|
129 | );
|
130 | });
|
131 |
|
132 | it('should work with the standard timeout', function() {
|
133 | this.timeout(client.cfg.decisionTreeRetrievalTimeout + 2000);
|
134 | const lastOperation = _.last(_.last(CONFIGURATION_2_OPERATIONS));
|
135 | return client.getAgentDecisionTree(agent.id, lastOperation.timestamp)
|
136 | .then((treeJson) => {
|
137 | expect(treeJson).to.be.ok;
|
138 | const { _version, configuration, trees } = parse(treeJson);
|
139 | expect(trees).to.be.ok;
|
140 | expect(_version).to.be.ok;
|
141 | expect(configuration).to.be.deep.equal(CONFIGURATION_2);
|
142 | });
|
143 | });
|
144 | });
|
145 | });
|