@fluid-experimental/odsp-end-to-end-tests 2.0.0-dev.7.4.0.221926
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.
- package/.eslintrc.cjs +14 -0
- package/CHANGELOG.md +3 -0
- package/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/test/OdspClientFactory.js +48 -0
- package/dist/test/OdspClientFactory.js.map +1 -0
- package/dist/test/OdspTokenFactory.js +53 -0
- package/dist/test/OdspTokenFactory.js.map +1 -0
- package/dist/test/TestDataObject.js +46 -0
- package/dist/test/TestDataObject.js.map +1 -0
- package/dist/test/audience.spec.js +142 -0
- package/dist/test/audience.spec.js.map +1 -0
- package/dist/test/containerCreate.spec.js +115 -0
- package/dist/test/containerCreate.spec.js.map +1 -0
- package/dist/test/ddsTests.spec.js +198 -0
- package/dist/test/ddsTests.spec.js.map +1 -0
- package/dist/test/utils.js +44 -0
- package/dist/test/utils.js.map +1 -0
- package/package.json +97 -0
- package/src/test/.mocharc.js +11 -0
- package/src/test/OdspClientFactory.ts +72 -0
- package/src/test/OdspTokenFactory.ts +76 -0
- package/src/test/TestDataObject.ts +63 -0
- package/src/test/audience.spec.ts +186 -0
- package/src/test/containerCreate.spec.ts +156 -0
- package/src/test/ddsTests.spec.ts +267 -0
- package/src/test/tsconfig.json +9 -0
- package/src/test/utils.ts +48 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/*!
|
|
4
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
5
|
+
* Licensed under the MIT License.
|
|
6
|
+
*/
|
|
7
|
+
const node_assert_1 = require("node:assert");
|
|
8
|
+
const map_1 = require("@fluidframework/map");
|
|
9
|
+
const test_utils_1 = require("@fluidframework/test-utils");
|
|
10
|
+
const container_loader_1 = require("@fluidframework/container-loader");
|
|
11
|
+
const OdspClientFactory_1 = require("./OdspClientFactory");
|
|
12
|
+
const TestDataObject_1 = require("./TestDataObject");
|
|
13
|
+
const utils_1 = require("./utils");
|
|
14
|
+
const clientCreds = {
|
|
15
|
+
clientId: "process.env.odsp__client__client__id",
|
|
16
|
+
clientSecret: "process.env.odsp__client__client__secret",
|
|
17
|
+
username: "process.env.odsp__client__login__username",
|
|
18
|
+
password: "process.env.odsp__client__login__password",
|
|
19
|
+
};
|
|
20
|
+
describe("Fluid data updates", () => {
|
|
21
|
+
const connectTimeoutMs = 10000;
|
|
22
|
+
let client;
|
|
23
|
+
let schema;
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
client = (0, OdspClientFactory_1.createOdspClient)(clientCreds);
|
|
26
|
+
schema = {
|
|
27
|
+
initialObjects: {
|
|
28
|
+
map1: map_1.SharedMap,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Scenario: test when an Odsp Client container is created,
|
|
34
|
+
* it can set the initial objects.
|
|
35
|
+
*
|
|
36
|
+
* Expected behavior: an error should not be thrown nor should a rejected promise
|
|
37
|
+
* be returned.
|
|
38
|
+
*/
|
|
39
|
+
it("can set DDSes as initial objects for a container", async () => {
|
|
40
|
+
const { container: newContainer } = await client.createContainer(schema);
|
|
41
|
+
const itemId = await newContainer.attach();
|
|
42
|
+
if (newContainer.connectionState !== container_loader_1.ConnectionState.Connected) {
|
|
43
|
+
await (0, test_utils_1.timeoutPromise)((resolve) => newContainer.once("connected", () => resolve()), {
|
|
44
|
+
durationMs: connectTimeoutMs,
|
|
45
|
+
errorMsg: "container connect() timeout",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const resources = client.getContainer(itemId, schema);
|
|
49
|
+
await node_assert_1.strict.doesNotReject(resources, () => true, "container cannot be retrieved from ODSP");
|
|
50
|
+
const { container } = await resources;
|
|
51
|
+
node_assert_1.strict.deepStrictEqual(Object.keys(container.initialObjects), Object.keys(schema.initialObjects));
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* Scenario: test if initialObjects passed into the container functions correctly.
|
|
55
|
+
*
|
|
56
|
+
* Expected behavior: initialObjects value loaded in two different containers should mirror
|
|
57
|
+
* each other after value is changed.
|
|
58
|
+
*/
|
|
59
|
+
it("can change DDSes within initialObjects value", async () => {
|
|
60
|
+
const { container } = await client.createContainer(schema);
|
|
61
|
+
const itemId = await container.attach();
|
|
62
|
+
if (container.connectionState !== container_loader_1.ConnectionState.Connected) {
|
|
63
|
+
await (0, test_utils_1.timeoutPromise)((resolve) => container.once("connected", () => resolve()), {
|
|
64
|
+
durationMs: connectTimeoutMs,
|
|
65
|
+
errorMsg: "container connect() timeout",
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const initialObjectsCreate = container.initialObjects;
|
|
69
|
+
const map1Create = initialObjectsCreate.map1;
|
|
70
|
+
map1Create.set("new-key", "new-value");
|
|
71
|
+
const valueCreate = map1Create.get("new-key");
|
|
72
|
+
const { container: containerGet } = await client.getContainer(itemId, schema);
|
|
73
|
+
const map1Get = containerGet.initialObjects.map1;
|
|
74
|
+
const valueGet = await (0, utils_1.mapWait)(map1Get, "new-key");
|
|
75
|
+
node_assert_1.strict.strictEqual(valueGet, valueCreate, "container can't change initial objects");
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* Scenario: test if we can create DataObjects through initialObjects schema.
|
|
79
|
+
*
|
|
80
|
+
* Expected behavior: DataObjects can be retrieved from the original and loaded container.
|
|
81
|
+
*/
|
|
82
|
+
it("can set DataObjects as initial objects for a container", async () => {
|
|
83
|
+
const doSchema = {
|
|
84
|
+
initialObjects: {
|
|
85
|
+
mdo1: TestDataObject_1.TestDataObject,
|
|
86
|
+
mdo2: TestDataObject_1.CounterTestDataObject,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
const { container } = await client.createContainer(doSchema);
|
|
90
|
+
const itemId = await container.attach();
|
|
91
|
+
if (container.connectionState !== container_loader_1.ConnectionState.Connected) {
|
|
92
|
+
await (0, test_utils_1.timeoutPromise)((resolve) => container.once("connected", () => resolve()), {
|
|
93
|
+
durationMs: connectTimeoutMs,
|
|
94
|
+
errorMsg: "container connect() timeout",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
const initialObjectsCreate = container.initialObjects;
|
|
98
|
+
(0, node_assert_1.strict)(initialObjectsCreate.mdo1 instanceof TestDataObject_1.TestDataObject, "container returns the wrong type for mdo1");
|
|
99
|
+
(0, node_assert_1.strict)(initialObjectsCreate.mdo2 instanceof TestDataObject_1.CounterTestDataObject, "container returns the wrong type for mdo2");
|
|
100
|
+
const { container: containerGet } = await client.getContainer(itemId, doSchema);
|
|
101
|
+
const initialObjectsGet = containerGet.initialObjects;
|
|
102
|
+
(0, node_assert_1.strict)(initialObjectsGet.mdo1 instanceof TestDataObject_1.TestDataObject, "container returns the wrong type for mdo1");
|
|
103
|
+
(0, node_assert_1.strict)(initialObjectsCreate.mdo2 instanceof TestDataObject_1.CounterTestDataObject, "container returns the wrong type for mdo2");
|
|
104
|
+
});
|
|
105
|
+
/**
|
|
106
|
+
* Scenario: test if we can create multiple DataObjects of the same type
|
|
107
|
+
*
|
|
108
|
+
* Expected behavior: DataObjects of the same type can be retrieved from the
|
|
109
|
+
* original and loaded container.
|
|
110
|
+
* TODO: Known bug that needs to be re-tested once fixed.
|
|
111
|
+
*/
|
|
112
|
+
it("can use multiple DataObjects of the same type", async () => {
|
|
113
|
+
const doSchema = {
|
|
114
|
+
initialObjects: {
|
|
115
|
+
mdo1: TestDataObject_1.TestDataObject,
|
|
116
|
+
mdo2: TestDataObject_1.CounterTestDataObject,
|
|
117
|
+
mdo3: TestDataObject_1.CounterTestDataObject,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
const { container } = await client.createContainer(doSchema);
|
|
121
|
+
const itemId = await container.attach();
|
|
122
|
+
if (container.connectionState !== container_loader_1.ConnectionState.Connected) {
|
|
123
|
+
await (0, test_utils_1.timeoutPromise)((resolve) => container.once("connected", () => resolve()), {
|
|
124
|
+
durationMs: connectTimeoutMs,
|
|
125
|
+
errorMsg: "container connect() timeout",
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const initialObjectsCreate = container.initialObjects;
|
|
129
|
+
(0, node_assert_1.strict)(initialObjectsCreate.mdo1 instanceof TestDataObject_1.TestDataObject, "container returns the wrong type for mdo1");
|
|
130
|
+
(0, node_assert_1.strict)(initialObjectsCreate.mdo2 instanceof TestDataObject_1.CounterTestDataObject, "container returns the wrong type for mdo2");
|
|
131
|
+
(0, node_assert_1.strict)(initialObjectsCreate.mdo3 instanceof TestDataObject_1.CounterTestDataObject, "container returns the wrong type for mdo3");
|
|
132
|
+
const { container: containerGet } = await client.getContainer(itemId, doSchema);
|
|
133
|
+
const initialObjectsGet = containerGet.initialObjects;
|
|
134
|
+
(0, node_assert_1.strict)(initialObjectsGet.mdo1 instanceof TestDataObject_1.TestDataObject, "container returns the wrong type for mdo1");
|
|
135
|
+
(0, node_assert_1.strict)(initialObjectsCreate.mdo2 instanceof TestDataObject_1.CounterTestDataObject, "container returns the wrong type for mdo2");
|
|
136
|
+
(0, node_assert_1.strict)(initialObjectsCreate.mdo3 instanceof TestDataObject_1.CounterTestDataObject, "container returns the wrong type for mdo3");
|
|
137
|
+
});
|
|
138
|
+
/**
|
|
139
|
+
* Scenario: test if we can change DataObject value contained within initialObjects
|
|
140
|
+
*
|
|
141
|
+
* Expected behavior: DataObject changes are correctly reflected on original and loaded containers
|
|
142
|
+
*/
|
|
143
|
+
it("can change DataObjects within initialObjects value", async () => {
|
|
144
|
+
const doSchema = {
|
|
145
|
+
initialObjects: {
|
|
146
|
+
mdo1: TestDataObject_1.TestDataObject,
|
|
147
|
+
mdo2: TestDataObject_1.CounterTestDataObject,
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
const { container } = await client.createContainer(doSchema);
|
|
151
|
+
const initialObjectsCreate = container.initialObjects;
|
|
152
|
+
const mdo2 = initialObjectsCreate.mdo2;
|
|
153
|
+
mdo2.increment();
|
|
154
|
+
mdo2.increment();
|
|
155
|
+
mdo2.increment();
|
|
156
|
+
node_assert_1.strict.strictEqual(mdo2.value, 3);
|
|
157
|
+
const itemId = await container.attach();
|
|
158
|
+
if (container.connectionState !== container_loader_1.ConnectionState.Connected) {
|
|
159
|
+
await (0, test_utils_1.timeoutPromise)((resolve) => container.once("connected", () => resolve()), {
|
|
160
|
+
durationMs: connectTimeoutMs,
|
|
161
|
+
errorMsg: "container connect() timeout",
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
const { container: containerGet } = await client.getContainer(itemId, doSchema);
|
|
165
|
+
const initialObjectsGet = containerGet.initialObjects;
|
|
166
|
+
const mdo2get = initialObjectsGet.mdo2;
|
|
167
|
+
node_assert_1.strict.strictEqual(mdo2get.value, 3);
|
|
168
|
+
mdo2get.increment();
|
|
169
|
+
mdo2get.increment();
|
|
170
|
+
node_assert_1.strict.strictEqual(mdo2get.value, 5);
|
|
171
|
+
});
|
|
172
|
+
/**
|
|
173
|
+
* Scenario: test if the optional schema parameter, dynamicObjectTypes (custom data objects),
|
|
174
|
+
* can be added during runtime and be returned by the container.
|
|
175
|
+
*
|
|
176
|
+
* Expected behavior: added loadable object can be retrieved from the container. Loadable
|
|
177
|
+
* object's id and container config ID should be identical since it's now attached to
|
|
178
|
+
* the container.
|
|
179
|
+
*/
|
|
180
|
+
it("can create/add loadable objects (custom data object) dynamically during runtime", async () => {
|
|
181
|
+
const dynamicSchema = {
|
|
182
|
+
initialObjects: {
|
|
183
|
+
map1: map_1.SharedMap,
|
|
184
|
+
},
|
|
185
|
+
dynamicObjectTypes: [TestDataObject_1.TestDataObject],
|
|
186
|
+
};
|
|
187
|
+
const { container } = await client.createContainer(dynamicSchema);
|
|
188
|
+
await container.attach();
|
|
189
|
+
const newDo = await container.create(TestDataObject_1.TestDataObject);
|
|
190
|
+
node_assert_1.strict.ok(newDo?.handle);
|
|
191
|
+
const map1 = container.initialObjects.map1;
|
|
192
|
+
map1.set("new-pair-id", newDo.handle);
|
|
193
|
+
const handle = await map1.get("new-pair-id");
|
|
194
|
+
const obj = await handle?.get();
|
|
195
|
+
node_assert_1.strict.ok(obj, "container added dynamic objects incorrectly");
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
//# sourceMappingURL=ddsTests.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ddsTests.spec.js","sourceRoot":"","sources":["../../src/test/ddsTests.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { strict as assert } from \"node:assert\";\n\nimport { OdspClient } from \"@fluid-experimental/odsp-client\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { ContainerSchema } from \"@fluidframework/fluid-static\";\nimport { SharedMap } from \"@fluidframework/map\";\nimport { timeoutPromise } from \"@fluidframework/test-utils\";\n\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport { OdspTestCredentials, createOdspClient } from \"./OdspClientFactory\";\nimport { CounterTestDataObject, TestDataObject } from \"./TestDataObject\";\nimport { mapWait } from \"./utils\";\n\nconst clientCreds: OdspTestCredentials = {\n\tclientId: \"process.env.odsp__client__client__id\",\n\tclientSecret: \"process.env.odsp__client__client__secret\",\n\tusername: \"process.env.odsp__client__login__username\",\n\tpassword: \"process.env.odsp__client__login__password\",\n};\n\ndescribe(\"Fluid data updates\", () => {\n\tconst connectTimeoutMs = 10_000;\n\tlet client: OdspClient;\n\tlet schema: ContainerSchema;\n\n\tbeforeEach(() => {\n\t\tclient = createOdspClient(clientCreds);\n\t\tschema = {\n\t\t\tinitialObjects: {\n\t\t\t\tmap1: SharedMap,\n\t\t\t},\n\t\t};\n\t});\n\n\t/**\n\t * Scenario: test when an Odsp Client container is created,\n\t * it can set the initial objects.\n\t *\n\t * Expected behavior: an error should not be thrown nor should a rejected promise\n\t * be returned.\n\t */\n\tit(\"can set DDSes as initial objects for a container\", async () => {\n\t\tconst { container: newContainer } = await client.createContainer(schema);\n\t\tconst itemId = await newContainer.attach();\n\n\t\tif (newContainer.connectionState !== ConnectionState.Connected) {\n\t\t\tawait timeoutPromise((resolve) => newContainer.once(\"connected\", () => resolve()), {\n\t\t\t\tdurationMs: connectTimeoutMs,\n\t\t\t\terrorMsg: \"container connect() timeout\",\n\t\t\t});\n\t\t}\n\n\t\tconst resources = client.getContainer(itemId, schema);\n\t\tawait assert.doesNotReject(\n\t\t\tresources,\n\t\t\t() => true,\n\t\t\t\"container cannot be retrieved from ODSP\",\n\t\t);\n\n\t\tconst { container } = await resources;\n\t\tassert.deepStrictEqual(\n\t\t\tObject.keys(container.initialObjects),\n\t\t\tObject.keys(schema.initialObjects),\n\t\t);\n\t});\n\n\t/**\n\t * Scenario: test if initialObjects passed into the container functions correctly.\n\t *\n\t * Expected behavior: initialObjects value loaded in two different containers should mirror\n\t * each other after value is changed.\n\t */\n\tit(\"can change DDSes within initialObjects value\", async () => {\n\t\tconst { container } = await client.createContainer(schema);\n\t\tconst itemId = await container.attach();\n\n\t\tif (container.connectionState !== ConnectionState.Connected) {\n\t\t\tawait timeoutPromise((resolve) => container.once(\"connected\", () => resolve()), {\n\t\t\t\tdurationMs: connectTimeoutMs,\n\t\t\t\terrorMsg: \"container connect() timeout\",\n\t\t\t});\n\t\t}\n\n\t\tconst initialObjectsCreate = container.initialObjects;\n\t\tconst map1Create = initialObjectsCreate.map1 as SharedMap;\n\t\tmap1Create.set(\"new-key\", \"new-value\");\n\t\tconst valueCreate: string | undefined = map1Create.get(\"new-key\");\n\n\t\tconst { container: containerGet } = await client.getContainer(itemId, schema);\n\t\tconst map1Get = containerGet.initialObjects.map1 as SharedMap;\n\t\tconst valueGet: string | undefined = await mapWait(map1Get, \"new-key\");\n\t\tassert.strictEqual(valueGet, valueCreate, \"container can't change initial objects\");\n\t});\n\n\t/**\n\t * Scenario: test if we can create DataObjects through initialObjects schema.\n\t *\n\t * Expected behavior: DataObjects can be retrieved from the original and loaded container.\n\t */\n\tit(\"can set DataObjects as initial objects for a container\", async () => {\n\t\tconst doSchema: ContainerSchema = {\n\t\t\tinitialObjects: {\n\t\t\t\tmdo1: TestDataObject,\n\t\t\t\tmdo2: CounterTestDataObject,\n\t\t\t},\n\t\t};\n\t\tconst { container } = await client.createContainer(doSchema);\n\t\tconst itemId = await container.attach();\n\n\t\tif (container.connectionState !== ConnectionState.Connected) {\n\t\t\tawait timeoutPromise((resolve) => container.once(\"connected\", () => resolve()), {\n\t\t\t\tdurationMs: connectTimeoutMs,\n\t\t\t\terrorMsg: \"container connect() timeout\",\n\t\t\t});\n\t\t}\n\n\t\tconst initialObjectsCreate = container.initialObjects;\n\t\tassert(\n\t\t\tinitialObjectsCreate.mdo1 instanceof TestDataObject,\n\t\t\t\"container returns the wrong type for mdo1\",\n\t\t);\n\t\tassert(\n\t\t\tinitialObjectsCreate.mdo2 instanceof CounterTestDataObject,\n\t\t\t\"container returns the wrong type for mdo2\",\n\t\t);\n\n\t\tconst { container: containerGet } = await client.getContainer(itemId, doSchema);\n\t\tconst initialObjectsGet = containerGet.initialObjects;\n\t\tassert(\n\t\t\tinitialObjectsGet.mdo1 instanceof TestDataObject,\n\t\t\t\"container returns the wrong type for mdo1\",\n\t\t);\n\t\tassert(\n\t\t\tinitialObjectsCreate.mdo2 instanceof CounterTestDataObject,\n\t\t\t\"container returns the wrong type for mdo2\",\n\t\t);\n\t});\n\n\t/**\n\t * Scenario: test if we can create multiple DataObjects of the same type\n\t *\n\t * Expected behavior: DataObjects of the same type can be retrieved from the\n\t * original and loaded container.\n\t * TODO: Known bug that needs to be re-tested once fixed.\n\t */\n\tit(\"can use multiple DataObjects of the same type\", async () => {\n\t\tconst doSchema: ContainerSchema = {\n\t\t\tinitialObjects: {\n\t\t\t\tmdo1: TestDataObject,\n\t\t\t\tmdo2: CounterTestDataObject,\n\t\t\t\tmdo3: CounterTestDataObject,\n\t\t\t},\n\t\t};\n\t\tconst { container } = await client.createContainer(doSchema);\n\t\tconst itemId = await container.attach();\n\n\t\tif (container.connectionState !== ConnectionState.Connected) {\n\t\t\tawait timeoutPromise((resolve) => container.once(\"connected\", () => resolve()), {\n\t\t\t\tdurationMs: connectTimeoutMs,\n\t\t\t\terrorMsg: \"container connect() timeout\",\n\t\t\t});\n\t\t}\n\n\t\tconst initialObjectsCreate = container.initialObjects;\n\t\tassert(\n\t\t\tinitialObjectsCreate.mdo1 instanceof TestDataObject,\n\t\t\t\"container returns the wrong type for mdo1\",\n\t\t);\n\t\tassert(\n\t\t\tinitialObjectsCreate.mdo2 instanceof CounterTestDataObject,\n\t\t\t\"container returns the wrong type for mdo2\",\n\t\t);\n\t\tassert(\n\t\t\tinitialObjectsCreate.mdo3 instanceof CounterTestDataObject,\n\t\t\t\"container returns the wrong type for mdo3\",\n\t\t);\n\n\t\tconst { container: containerGet } = await client.getContainer(itemId, doSchema);\n\t\tconst initialObjectsGet = containerGet.initialObjects;\n\t\tassert(\n\t\t\tinitialObjectsGet.mdo1 instanceof TestDataObject,\n\t\t\t\"container returns the wrong type for mdo1\",\n\t\t);\n\t\tassert(\n\t\t\tinitialObjectsCreate.mdo2 instanceof CounterTestDataObject,\n\t\t\t\"container returns the wrong type for mdo2\",\n\t\t);\n\t\tassert(\n\t\t\tinitialObjectsCreate.mdo3 instanceof CounterTestDataObject,\n\t\t\t\"container returns the wrong type for mdo3\",\n\t\t);\n\t});\n\n\t/**\n\t * Scenario: test if we can change DataObject value contained within initialObjects\n\t *\n\t * Expected behavior: DataObject changes are correctly reflected on original and loaded containers\n\t */\n\tit(\"can change DataObjects within initialObjects value\", async () => {\n\t\tconst doSchema: ContainerSchema = {\n\t\t\tinitialObjects: {\n\t\t\t\tmdo1: TestDataObject,\n\t\t\t\tmdo2: CounterTestDataObject,\n\t\t\t},\n\t\t};\n\t\tconst { container } = await client.createContainer(doSchema);\n\t\tconst initialObjectsCreate = container.initialObjects;\n\t\tconst mdo2 = initialObjectsCreate.mdo2 as CounterTestDataObject;\n\t\tmdo2.increment();\n\t\tmdo2.increment();\n\t\tmdo2.increment();\n\n\t\tassert.strictEqual(mdo2.value, 3);\n\n\t\tconst itemId = await container.attach();\n\n\t\tif (container.connectionState !== ConnectionState.Connected) {\n\t\t\tawait timeoutPromise((resolve) => container.once(\"connected\", () => resolve()), {\n\t\t\t\tdurationMs: connectTimeoutMs,\n\t\t\t\terrorMsg: \"container connect() timeout\",\n\t\t\t});\n\t\t}\n\n\t\tconst { container: containerGet } = await client.getContainer(itemId, doSchema);\n\t\tconst initialObjectsGet = containerGet.initialObjects;\n\t\tconst mdo2get = initialObjectsGet.mdo2 as CounterTestDataObject;\n\n\t\tassert.strictEqual(mdo2get.value, 3);\n\n\t\tmdo2get.increment();\n\t\tmdo2get.increment();\n\t\tassert.strictEqual(mdo2get.value, 5);\n\t});\n\n\t/**\n\t * Scenario: test if the optional schema parameter, dynamicObjectTypes (custom data objects),\n\t * can be added during runtime and be returned by the container.\n\t *\n\t * Expected behavior: added loadable object can be retrieved from the container. Loadable\n\t * object's id and container config ID should be identical since it's now attached to\n\t * the container.\n\t */\n\tit(\"can create/add loadable objects (custom data object) dynamically during runtime\", async () => {\n\t\tconst dynamicSchema: ContainerSchema = {\n\t\t\tinitialObjects: {\n\t\t\t\tmap1: SharedMap,\n\t\t\t},\n\t\t\tdynamicObjectTypes: [TestDataObject],\n\t\t};\n\n\t\tconst { container } = await client.createContainer(dynamicSchema);\n\t\tawait container.attach();\n\n\t\tconst newDo = await container.create(TestDataObject);\n\t\tassert.ok(newDo?.handle);\n\n\t\tconst map1 = container.initialObjects.map1 as SharedMap;\n\t\tmap1.set(\"new-pair-id\", newDo.handle);\n\t\tconst handle: IFluidHandle | undefined = await map1.get(\"new-pair-id\");\n\t\tconst obj: unknown = await handle?.get();\n\t\tassert.ok(obj, \"container added dynamic objects incorrectly\");\n\t});\n});\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.mapWait = exports.waitForMember = void 0;
|
|
8
|
+
const waitForMember = async (audience, username) => {
|
|
9
|
+
const allMembers = audience.getMembers();
|
|
10
|
+
const member = allMembers.get(username);
|
|
11
|
+
if (member !== undefined) {
|
|
12
|
+
return member;
|
|
13
|
+
}
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
const handler = (clientId, newMember) => {
|
|
16
|
+
if (newMember.userId === username) {
|
|
17
|
+
resolve(newMember);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
audience.on("memberAdded", handler);
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
exports.waitForMember = waitForMember;
|
|
24
|
+
const mapWait = async (map, key) => {
|
|
25
|
+
const maybeValue = map.get(key);
|
|
26
|
+
if (maybeValue !== undefined) {
|
|
27
|
+
return maybeValue;
|
|
28
|
+
}
|
|
29
|
+
return new Promise((resolve) => {
|
|
30
|
+
const handler = (changed) => {
|
|
31
|
+
if (changed.key === key) {
|
|
32
|
+
map.off("valueChanged", handler);
|
|
33
|
+
const value = map.get(changed.key);
|
|
34
|
+
if (value === undefined) {
|
|
35
|
+
throw new Error("Unexpected valueChanged result");
|
|
36
|
+
}
|
|
37
|
+
resolve(value);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
map.on("valueChanged", handler);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
exports.mapWait = mapWait;
|
|
44
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAMI,MAAM,aAAa,GAAG,KAAK,EACjC,QAAuB,EACvB,QAAgB,EACM,EAAE;IACxB,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,MAAM,KAAK,SAAS,EAAE;QACzB,OAAO,MAAM,CAAC;KACd;IACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,MAAM,OAAO,GAAG,CAAC,QAAgB,EAAE,SAAkB,EAAQ,EAAE;YAC9D,IAAI,SAAS,CAAC,MAAM,KAAK,QAAQ,EAAE;gBAClC,OAAO,CAAC,SAAuB,CAAC,CAAC;aACjC;QACF,CAAC,CAAC;QACF,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAjBW,QAAA,aAAa,iBAiBxB;AAEK,MAAM,OAAO,GAAG,KAAK,EAAK,GAAe,EAAE,GAAW,EAAc,EAAE;IAC5E,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;IACnC,IAAI,UAAU,KAAK,SAAS,EAAE;QAC7B,OAAO,UAAU,CAAC;KAClB;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,MAAM,OAAO,GAAG,CAAC,OAAsB,EAAQ,EAAE;YAChD,IAAI,OAAO,CAAC,GAAG,KAAK,GAAG,EAAE;gBACxB,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;gBACjC,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAI,OAAO,CAAC,GAAG,CAAC,CAAC;gBACtC,IAAI,KAAK,KAAK,SAAS,EAAE;oBACxB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;iBAClD;gBACD,OAAO,CAAC,KAAK,CAAC,CAAC;aACf;QACF,CAAC,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAnBW,QAAA,OAAO,WAmBlB","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { OdspMember, IOdspAudience } from \"@fluid-experimental/odsp-client\";\nimport { IMember } from \"@fluidframework/fluid-static\";\nimport { ISharedMap, IValueChanged } from \"@fluidframework/map\";\n\nexport const waitForMember = async (\n\taudience: IOdspAudience,\n\tusername: string,\n): Promise<OdspMember> => {\n\tconst allMembers = audience.getMembers();\n\tconst member = allMembers.get(username);\n\tif (member !== undefined) {\n\t\treturn member;\n\t}\n\treturn new Promise((resolve) => {\n\t\tconst handler = (clientId: string, newMember: IMember): void => {\n\t\t\tif (newMember.userId === username) {\n\t\t\t\tresolve(newMember as OdspMember);\n\t\t\t}\n\t\t};\n\t\taudience.on(\"memberAdded\", handler);\n\t});\n};\n\nexport const mapWait = async <T>(map: ISharedMap, key: string): Promise<T> => {\n\tconst maybeValue = map.get<T>(key);\n\tif (maybeValue !== undefined) {\n\t\treturn maybeValue;\n\t}\n\n\treturn new Promise((resolve) => {\n\t\tconst handler = (changed: IValueChanged): void => {\n\t\t\tif (changed.key === key) {\n\t\t\t\tmap.off(\"valueChanged\", handler);\n\t\t\t\tconst value = map.get<T>(changed.key);\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tthrow new Error(\"Unexpected valueChanged result\");\n\t\t\t\t}\n\t\t\t\tresolve(value);\n\t\t\t}\n\t\t};\n\t\tmap.on(\"valueChanged\", handler);\n\t});\n};\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fluid-experimental/odsp-end-to-end-tests",
|
|
3
|
+
"version": "2.0.0-dev.7.4.0.221926",
|
|
4
|
+
"description": "Odsp client end to end tests",
|
|
5
|
+
"homepage": "https://fluidframework.com",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/microsoft/FluidFramework.git",
|
|
9
|
+
"directory": "packages/service-clients/end-to-end-tests/odsp-client"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "Microsoft and contributors",
|
|
13
|
+
"sideEffects": false,
|
|
14
|
+
"c8": {
|
|
15
|
+
"all": true,
|
|
16
|
+
"cache-dir": "nyc/.cache",
|
|
17
|
+
"exclude": [
|
|
18
|
+
"src/test/**/*.ts",
|
|
19
|
+
"dist/test/**/*.js"
|
|
20
|
+
],
|
|
21
|
+
"exclude-after-remap": false,
|
|
22
|
+
"include": [
|
|
23
|
+
"src/**/*.ts",
|
|
24
|
+
"dist/**/*.js"
|
|
25
|
+
],
|
|
26
|
+
"report-dir": "nyc/report",
|
|
27
|
+
"reporter": [
|
|
28
|
+
"cobertura",
|
|
29
|
+
"html",
|
|
30
|
+
"text"
|
|
31
|
+
],
|
|
32
|
+
"temp-directory": "nyc/.nyc_output"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@fluid-experimental/odsp-client": "2.0.0-dev.7.4.0.221926",
|
|
36
|
+
"@fluidframework/aqueduct": "2.0.0-dev.7.4.0.221926",
|
|
37
|
+
"@fluidframework/container-definitions": "2.0.0-dev.7.4.0.221926",
|
|
38
|
+
"@fluidframework/container-loader": "2.0.0-dev.7.4.0.221926",
|
|
39
|
+
"@fluidframework/core-interfaces": "2.0.0-dev.7.4.0.221926",
|
|
40
|
+
"@fluidframework/counter": "2.0.0-dev.7.4.0.221926",
|
|
41
|
+
"@fluidframework/fluid-static": "2.0.0-dev.7.4.0.221926",
|
|
42
|
+
"@fluidframework/map": "2.0.0-dev.7.4.0.221926",
|
|
43
|
+
"@fluidframework/matrix": "2.0.0-dev.7.4.0.221926",
|
|
44
|
+
"@fluidframework/mocha-test-setup": "2.0.0-dev.7.4.0.221926",
|
|
45
|
+
"@fluidframework/odsp-doclib-utils": "2.0.0-dev.7.4.0.221926",
|
|
46
|
+
"@fluidframework/odsp-driver-definitions": "2.0.0-dev.7.4.0.221926",
|
|
47
|
+
"@fluidframework/sequence": "2.0.0-dev.7.4.0.221926",
|
|
48
|
+
"@fluidframework/telemetry-utils": "2.0.0-dev.7.4.0.221926",
|
|
49
|
+
"@fluidframework/test-runtime-utils": "2.0.0-dev.7.4.0.221926",
|
|
50
|
+
"@fluidframework/test-utils": "2.0.0-dev.7.4.0.221926",
|
|
51
|
+
"cross-env": "^7.0.3",
|
|
52
|
+
"mocha": "^10.2.0",
|
|
53
|
+
"mocha-json-output-reporter": "^2.0.1",
|
|
54
|
+
"mocha-multi-reporters": "^1.5.1",
|
|
55
|
+
"moment": "^2.21.0",
|
|
56
|
+
"prettier": "~3.0.3",
|
|
57
|
+
"sinon": "^7.4.2",
|
|
58
|
+
"uuid": "^9.0.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@fluidframework/build-common": "^2.0.3",
|
|
62
|
+
"@fluidframework/build-tools": "^0.28.0",
|
|
63
|
+
"@fluidframework/eslint-config-fluid": "^3.1.0",
|
|
64
|
+
"@types/mocha": "^9.1.1",
|
|
65
|
+
"@types/nock": "^9.3.0",
|
|
66
|
+
"@types/node": "^18.19.0",
|
|
67
|
+
"@types/uuid": "^9.0.2",
|
|
68
|
+
"c8": "^7.7.1",
|
|
69
|
+
"eslint": "~8.50.0",
|
|
70
|
+
"nock": "^13.3.3",
|
|
71
|
+
"rimraf": "^4.4.0",
|
|
72
|
+
"typescript": "~5.1.6"
|
|
73
|
+
},
|
|
74
|
+
"typeValidation": {
|
|
75
|
+
"disabled": true,
|
|
76
|
+
"broken": {}
|
|
77
|
+
},
|
|
78
|
+
"scripts": {
|
|
79
|
+
"build": "fluid-build . --task build",
|
|
80
|
+
"build:compile": "fluid-build . --task compile",
|
|
81
|
+
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
82
|
+
"clean": "rimraf --glob dist lib \"**/*.tsbuildinfo\" \"**/*.build.log\" nyc",
|
|
83
|
+
"eslint": "eslint --format stylish src",
|
|
84
|
+
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
85
|
+
"format": "npm run prettier:fix",
|
|
86
|
+
"lint": "npm run prettier && npm run eslint",
|
|
87
|
+
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
|
|
88
|
+
"prettier": "prettier --check . --cache --ignore-path ../../../../.prettierignore",
|
|
89
|
+
"prettier:fix": "prettier --write . --cache --ignore-path ../../../../.prettierignore",
|
|
90
|
+
"test": "npm run test:realsvc:odsp:run",
|
|
91
|
+
"test:coverage": "c8 npm test",
|
|
92
|
+
"test:realsvc:odsp": "cross-env npm run test:realsvc:odsp:run",
|
|
93
|
+
"test:realsvc:odsp:run": "mocha --recursive \"dist/test/*.spec.js\" --exit --timeout 20000 --config src/test/.mocharc.js",
|
|
94
|
+
"test:realsvc:run": "mocha dist/test --config src/test/.mocharc.js",
|
|
95
|
+
"test:realsvc:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:realsvc"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const packageDir = `${__dirname}/../..`;
|
|
9
|
+
const getFluidTestMochaConfig = require("@fluidframework/mocha-test-setup/mocharc-common.js");
|
|
10
|
+
const config = getFluidTestMochaConfig(packageDir);
|
|
11
|
+
module.exports = config;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { type ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
6
|
+
import { OdspClient, OdspConnectionConfig } from "@fluid-experimental/odsp-client";
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
IConfigProviderBase,
|
|
10
|
+
MockLogger,
|
|
11
|
+
createMultiSinkLogger,
|
|
12
|
+
} from "@fluidframework/telemetry-utils";
|
|
13
|
+
import { OdspTestTokenProvider } from "./OdspTokenFactory";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Interface representing the credentials required for testing odsp-client.
|
|
17
|
+
*/
|
|
18
|
+
export interface OdspTestCredentials {
|
|
19
|
+
clientId: string;
|
|
20
|
+
clientSecret: string;
|
|
21
|
+
username: string;
|
|
22
|
+
password: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* This function will determine if local or remote mode is required (based on FLUID_CLIENT), and return a new
|
|
27
|
+
* {@link OdspClient} instance based on the mode by setting the Connection config accordingly.
|
|
28
|
+
*/
|
|
29
|
+
export function createOdspClient(
|
|
30
|
+
creds: OdspTestCredentials,
|
|
31
|
+
logger?: MockLogger,
|
|
32
|
+
configProvider?: IConfigProviderBase,
|
|
33
|
+
): OdspClient {
|
|
34
|
+
const siteUrl = process.env.odsp__client__siteUrl as string;
|
|
35
|
+
const driveId = process.env.odsp__client__driveId as string;
|
|
36
|
+
if (siteUrl === "" || siteUrl === undefined) {
|
|
37
|
+
throw new Error("site url is missing");
|
|
38
|
+
}
|
|
39
|
+
if (driveId === "" || driveId === undefined) {
|
|
40
|
+
throw new Error("RaaS drive id is missing");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (
|
|
44
|
+
creds.clientId === undefined ||
|
|
45
|
+
creds.clientSecret === undefined ||
|
|
46
|
+
creds.username === undefined ||
|
|
47
|
+
creds.password === undefined
|
|
48
|
+
) {
|
|
49
|
+
throw new Error("Some of the odsp credentials are undefined");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const connectionProps: OdspConnectionConfig = {
|
|
53
|
+
siteUrl,
|
|
54
|
+
tokenProvider: new OdspTestTokenProvider(creds),
|
|
55
|
+
driveId,
|
|
56
|
+
};
|
|
57
|
+
const getLogger = (): ITelemetryBaseLogger | undefined => {
|
|
58
|
+
const testLogger = getTestLogger?.();
|
|
59
|
+
if (!logger && !testLogger) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
if (logger && testLogger) {
|
|
63
|
+
return createMultiSinkLogger({ loggers: [logger, testLogger] });
|
|
64
|
+
}
|
|
65
|
+
return logger ?? testLogger;
|
|
66
|
+
};
|
|
67
|
+
return new OdspClient({
|
|
68
|
+
connection: connectionProps,
|
|
69
|
+
logger: getLogger(),
|
|
70
|
+
configProvider,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
7
|
+
import { TokenResponse } from "@fluidframework/odsp-driver-definitions";
|
|
8
|
+
import {
|
|
9
|
+
IClientConfig,
|
|
10
|
+
TokenRequestCredentials,
|
|
11
|
+
getFetchTokenUrl,
|
|
12
|
+
unauthPostAsync,
|
|
13
|
+
} from "@fluidframework/odsp-doclib-utils";
|
|
14
|
+
import { IOdspTokenProvider } from "@fluid-experimental/odsp-client";
|
|
15
|
+
import { OdspTestCredentials } from "./OdspClientFactory";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* This class implements the IOdspTokenProvider interface and provides methods for fetching push and storage tokens.
|
|
19
|
+
*/
|
|
20
|
+
export class OdspTestTokenProvider implements IOdspTokenProvider {
|
|
21
|
+
private readonly creds: OdspTestCredentials;
|
|
22
|
+
|
|
23
|
+
constructor(credentials: OdspTestCredentials) {
|
|
24
|
+
this.creds = credentials;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public async fetchWebsocketToken(siteUrl: string, refresh: boolean): Promise<TokenResponse> {
|
|
28
|
+
const pushScope = "offline_access https://pushchannel.1drv.ms/PushChannel.ReadWrite.All";
|
|
29
|
+
const tokens = await this.fetchTokens(siteUrl, pushScope);
|
|
30
|
+
return {
|
|
31
|
+
fromCache: true,
|
|
32
|
+
token: tokens.accessToken,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public async fetchStorageToken(siteUrl: string, refresh: boolean): Promise<TokenResponse> {
|
|
37
|
+
const sharePointScopes = `${siteUrl}/Container.Selected`;
|
|
38
|
+
const tokens = await this.fetchTokens(siteUrl, sharePointScopes);
|
|
39
|
+
return {
|
|
40
|
+
fromCache: true,
|
|
41
|
+
token: tokens.accessToken,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private async fetchTokens(
|
|
46
|
+
siteUrl: string,
|
|
47
|
+
scope: string,
|
|
48
|
+
): Promise<{
|
|
49
|
+
accessToken: string;
|
|
50
|
+
refreshToken: string;
|
|
51
|
+
}> {
|
|
52
|
+
const server = new URL(siteUrl).host;
|
|
53
|
+
const clientConfig: IClientConfig = {
|
|
54
|
+
clientId: this.creds.clientId,
|
|
55
|
+
clientSecret: this.creds.clientSecret,
|
|
56
|
+
};
|
|
57
|
+
const credentials: TokenRequestCredentials = {
|
|
58
|
+
grant_type: "password",
|
|
59
|
+
username: this.creds.username,
|
|
60
|
+
password: this.creds.password,
|
|
61
|
+
};
|
|
62
|
+
const body = {
|
|
63
|
+
scope,
|
|
64
|
+
client_id: clientConfig.clientId,
|
|
65
|
+
client_secret: clientConfig.clientSecret,
|
|
66
|
+
...credentials,
|
|
67
|
+
};
|
|
68
|
+
const response = await unauthPostAsync(getFetchTokenUrl(server), new URLSearchParams(body));
|
|
69
|
+
|
|
70
|
+
const parsedResponse = await response.json();
|
|
71
|
+
const accessToken = parsedResponse.access_token;
|
|
72
|
+
const refreshToken = parsedResponse.refresh_token;
|
|
73
|
+
|
|
74
|
+
return { accessToken, refreshToken };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { DataObject, DataObjectFactory, IDataObjectProps } from "@fluidframework/aqueduct";
|
|
6
|
+
import { IFluidHandle } from "@fluidframework/core-interfaces";
|
|
7
|
+
import { SharedCounter } from "@fluidframework/counter";
|
|
8
|
+
|
|
9
|
+
export class TestDataObject extends DataObject {
|
|
10
|
+
public static readonly Name = "@fluid-example/test-data-object";
|
|
11
|
+
|
|
12
|
+
public static readonly factory = new DataObjectFactory(
|
|
13
|
+
TestDataObject.Name,
|
|
14
|
+
TestDataObject,
|
|
15
|
+
[],
|
|
16
|
+
{},
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
constructor(props: IDataObjectProps) {
|
|
20
|
+
super(props);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class CounterTestDataObject extends DataObject {
|
|
25
|
+
private _counter: SharedCounter | undefined;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Do setup work here
|
|
29
|
+
*/
|
|
30
|
+
protected async initializingFirstTime(): Promise<void> {
|
|
31
|
+
const counter = SharedCounter.create(this.runtime);
|
|
32
|
+
this.root.set("counter-key", counter.handle);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
protected async hasInitialized(): Promise<void> {
|
|
36
|
+
const counterHandle = this.root.get<IFluidHandle<SharedCounter>>("counter-key");
|
|
37
|
+
this._counter = await counterHandle?.get();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public static readonly Name = "@fluid-example/counter-test-data-object";
|
|
41
|
+
|
|
42
|
+
public static readonly factory = new DataObjectFactory(
|
|
43
|
+
CounterTestDataObject.Name,
|
|
44
|
+
CounterTestDataObject,
|
|
45
|
+
[SharedCounter.getFactory()],
|
|
46
|
+
{},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
public increment(): void {
|
|
50
|
+
this.counter.increment(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public get value(): number {
|
|
54
|
+
return this.counter.value;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private get counter(): SharedCounter {
|
|
58
|
+
if (this._counter === undefined) {
|
|
59
|
+
throw new Error("SharedCounter not initialized");
|
|
60
|
+
}
|
|
61
|
+
return this._counter;
|
|
62
|
+
}
|
|
63
|
+
}
|