@prismicio/e2e-tests-utils 1.2.0 → 1.3.0

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.
@@ -0,0 +1,178 @@
1
+ import axios, { AxiosInstance, AxiosResponse } from "axios";
2
+ import jwt from "jsonwebtoken";
3
+
4
+ import { ManageV2Config } from "../types";
5
+
6
+ import { extractCookie } from "../utils/cookies";
7
+
8
+ const ManageV2StaticAuthor = "prismic-e2e-tests-utils";
9
+
10
+ /**
11
+ * Client for interacting with ManageV2 routes to perform operations on
12
+ * repositories.
13
+ */
14
+ export class ManageV2Client {
15
+ readonly client: AxiosInstance; // Not private to have it available on tests
16
+ private token: string | null = null;
17
+
18
+ /**
19
+ * @param baseURL - The base URL of the Wroom app. ex: https://prismic.io
20
+ * @param config - ManageV2 configuration variable to call ManageV2.
21
+ */
22
+ constructor(baseUrl: string, config?: ManageV2Config | undefined) {
23
+ this.token = config ? this.generateToken(config) : null;
24
+
25
+ this.client = axios.create({
26
+ baseURL: `${baseUrl}/manageroutes/`,
27
+ withCredentials: true,
28
+ validateStatus: () => true,
29
+ headers: {
30
+ "User-Agent": "prismic-cli/prismic-e2e-tests-utils",
31
+ Authorization: `Bearer ${this.token}`,
32
+ },
33
+ });
34
+
35
+ // cookies are not forwarded automatically in a non-browser env
36
+ this.client.interceptors.response.use((response) => {
37
+ const cookies = response.headers["set-cookie"];
38
+ if (cookies && extractCookie(cookies, "SESSION")) {
39
+ this.client.defaults.headers["Cookie"] = cookies;
40
+ }
41
+
42
+ return response;
43
+ });
44
+ }
45
+
46
+ /**
47
+ * The function generates a JWT token using the provided configuration
48
+ * parameters.
49
+ *
50
+ * @param {ManageV2Config} config - The `config` parameter in the
51
+ * `generateToken` function is of type `ManageV2Config`. It contains the
52
+ * following properties:
53
+ *
54
+ * @returns A JSON Web Token (JWT) is being returned by the `generateToken`
55
+ * function. The token is signed using the provided `config.secret` with the
56
+ * HS256 algorithm and includes the specified audience and issuer values.
57
+ */
58
+ private generateToken(config: ManageV2Config): string {
59
+ return jwt.sign({}, config.secret, {
60
+ algorithm: "HS256",
61
+ audience: config.audience,
62
+ issuer: "prismic.io",
63
+ });
64
+ }
65
+
66
+ /**
67
+ * The function `assertTokenExist` checks if a token exists before executing a
68
+ * given function.
69
+ *
70
+ * @param f - The `assertTokenExist` function takes a function `f` as a
71
+ * parameter. This function `f` should accept a parameter of type
72
+ * `Parameters` and return a Promise that resolves to an AxiosResponse. The
73
+ * `assertTokenExist` function ensures that a token is not null before
74
+ * calling the provided
75
+ *
76
+ * @returns A function is being returned that takes a parameter of type
77
+ * Parameters and checks if the token is null. If the token is null, an
78
+ * error is thrown. Otherwise, the function f is called with the provided
79
+ * parameters.
80
+ */
81
+ private assertTokenExist<Parameters>(
82
+ f: (_: Parameters) => Promise<AxiosResponse>,
83
+ ) {
84
+ return (params: Parameters) => {
85
+ if (this.token === null) {
86
+ throw new Error(
87
+ "Undefined configuration for ManageV2 while trying to use it's routes",
88
+ );
89
+ } else {
90
+ return f(params);
91
+ }
92
+ };
93
+ }
94
+
95
+ getBaseURL(): string {
96
+ return this.client.getUri();
97
+ }
98
+
99
+ /**
100
+ * The function `toggleRolePerLocal` enable or disable the role per local
101
+ * feature
102
+ *
103
+ * @param repository - The Repository name
104
+ * @param enabled - The feature new status
105
+ */
106
+ toggleRolePerLocal = this.assertTokenExist(
107
+ (params: { repository: string; enabled: boolean }) => {
108
+ return this.client.post("/repository/toggleRolesPerLocale", {
109
+ domain: params.repository,
110
+ enabled: params.enabled,
111
+ author: ManageV2StaticAuthor,
112
+ });
113
+ },
114
+ );
115
+
116
+ /**
117
+ * The function `changePlan` changes the plan of a repository the database
118
+ *
119
+ * @param repository - The Repository name
120
+ * @param newPlanId - The new planId
121
+ * @param bypassManualBilling - Beware that using this will not verify that
122
+ * the database and Stripe are in sync
123
+ */
124
+ changePlan = this.assertTokenExist(
125
+ ({
126
+ repository,
127
+ newPlanId,
128
+ bypassManualBilling = false,
129
+ }: {
130
+ repository: string;
131
+ newPlanId: string;
132
+ bypassManualBilling?: boolean;
133
+ }) => {
134
+ return this.client.post(
135
+ `/repository/changePlan?bypassManualBilling=${bypassManualBilling}`,
136
+ {
137
+ domain: repository,
138
+ newPlan: newPlanId,
139
+ author: ManageV2StaticAuthor,
140
+ },
141
+ );
142
+ },
143
+ );
144
+
145
+ /**
146
+ * The function `addUserToRepository` adds a user corresponding to the email
147
+ * to the given repository
148
+ *
149
+ * @param repository - The Repository name
150
+ * @param email - The user email
151
+ */
152
+ addUserToRepository = this.assertTokenExist(
153
+ ({ repository, email }: { repository: string; email: string }) => {
154
+ return this.client.post("/repository/addUser", {
155
+ domain: repository,
156
+ email: email,
157
+ author: ManageV2StaticAuthor,
158
+ });
159
+ },
160
+ );
161
+
162
+ /**
163
+ * The function `removeUserFromRepository` removes a user corresponding to the
164
+ * email from the given repository
165
+ *
166
+ * @param repository - The Repository name
167
+ * @param email - The user email
168
+ */
169
+ removeUserFromRepository = this.assertTokenExist(
170
+ ({ repository, email }: { repository: string; email: string }) => {
171
+ return this.client.post("/repository/removeUser", {
172
+ domain: repository,
173
+ email: email,
174
+ author: ManageV2StaticAuthor,
175
+ });
176
+ },
177
+ );
178
+ }
@@ -1,6 +1,6 @@
1
1
  import axios, { AxiosInstance, AxiosResponse } from "axios";
2
2
 
3
- import { Credentials } from "../types";
3
+ import { AuthConfig } from "../types";
4
4
 
5
5
  import { extractCookie } from "../utils/cookies";
6
6
  import { logHttpResponse, logger } from "../utils/log";
@@ -20,7 +20,7 @@ export class WroomClient {
20
20
  */
21
21
  constructor(
22
22
  baseURL: string,
23
- private readonly auth: Credentials,
23
+ private readonly auth: AuthConfig,
24
24
  ) {
25
25
  this.client = axios.create({
26
26
  baseURL,
@@ -84,6 +84,46 @@ export class WroomClient {
84
84
  return response;
85
85
  }
86
86
 
87
+ /**
88
+ * Update the role of a user in the repository
89
+ *
90
+ * @param {string} repository - The repository name
91
+ * @param {string} email - The email of the user
92
+ * @param {string} role - The new role to be given
93
+ *
94
+ * @returns The Axios Reponse
95
+ */
96
+ async updateRole(
97
+ repository: string,
98
+ email: string,
99
+ role: string,
100
+ ): Promise<AxiosResponse> {
101
+ const params = new URLSearchParams({ email, profile: role });
102
+ const path = `/app/settings/users/profiles?${params.toString()}`;
103
+
104
+ return this.post(repository, path);
105
+ }
106
+
107
+ /**
108
+ * Update the role of a user in the repository
109
+ *
110
+ * @param {string} repository - The repository name
111
+ * @param {string} email - The email of the user
112
+ * @param {string} rolePerLocal - The role per local object
113
+ *
114
+ * @returns The Axios Reponse
115
+ */
116
+ async updateRolePerLocal(
117
+ repository: string,
118
+ email: string,
119
+ rolePerLocal: Record<string, string>,
120
+ ): Promise<AxiosResponse> {
121
+ const params = new URLSearchParams({ email });
122
+ const path = `/app/settings/users/rolesperlocale?${params.toString()}`;
123
+
124
+ return this.post(repository, path, rolePerLocal);
125
+ }
126
+
87
127
  /**
88
128
  * Authenticate Wroom to call Wroom unofficial endpoints.
89
129
  *
@@ -1,4 +1,4 @@
1
- import { Credentials } from "../types";
1
+ import { SetupConfiguration, UrlConfig } from "../types";
2
2
 
3
3
  import {
4
4
  AuthenticationClient,
@@ -6,6 +6,7 @@ import {
6
6
  } from "../clients/authenticationApi";
7
7
  import { createCoreApiClient } from "../clients/coreApi";
8
8
  import { createCustomTypesApiClient } from "../clients/customTypesApi";
9
+ import { ManageV2Client } from "../clients/manageV2";
9
10
  import { WroomClient } from "../clients/wroom";
10
11
  import { EnvVariableManager } from "../utils/envVariableManager";
11
12
  import { logHttpResponse, logger } from "../utils/log";
@@ -18,30 +19,29 @@ import { RepositoryConfig, RepositoryManager } from "./repository";
18
19
  * Factory method to create a RepositoriesManager to manage repositories test
19
20
  * data.
20
21
  *
21
- * @param urlConfig - If provided as an object:
22
+ * @param configuration - Global object containing the different configurations
23
+ * required to setup the RepositoriesManager.
22
24
  *
23
- * - {@link UrlConfig.baseURL}: The Prismic base URL.
24
- * - {@link UrlConfig.customTypesApi}: The base URL for the Custom Types API.
25
- * - {@link UrlConfig.authenticationApi}: The base URL for the Authentication API.
26
- *
27
- * If provided as a string: It is treated as the base URL for Prismic. Other
28
- * URLs (Custom Types API, Auth API) will be derived from it.
29
- * @param auth - The authentication credentials
25
+ * - {@link configuration.urlConfig}: Configuration around the API's URLs management.
26
+ * - {@link configuration.authConfig}: Configuration around the authentication of a user.
27
+ * - {@link configuration.manageV2Config}: Optional Configuration used to make calls to ManageV2.
30
28
  *
31
29
  * @returns An instance of {@link RepositoriesManager} to manage test data.
32
30
  */
33
31
  export const createRepositoriesManager = (
34
- urlConfig: UrlConfig | string,
35
- auth: Credentials,
32
+ configuration: SetupConfiguration,
36
33
  ): RepositoriesManager => {
37
- return new RepositoriesManager(urlConfig, auth);
34
+ return new RepositoriesManager(configuration);
38
35
  };
39
36
 
40
37
  /** Utility object to manage Prismic test data */
41
38
  export class RepositoriesManager {
42
- private readonly urls: UrlConfig;
39
+ private readonly config: Omit<SetupConfiguration, "urlConfig"> & {
40
+ urlConfig: UrlConfig;
41
+ };
43
42
  private readonly wroomClient: WroomClient;
44
43
  private readonly authClient: AuthenticationClient;
44
+ private readonly manageV2Client: ManageV2Client;
45
45
  /**
46
46
  * helper to keep track of repositories across independent test phases (setup,
47
47
  * teardown)
@@ -51,22 +51,31 @@ export class RepositoriesManager {
51
51
  );
52
52
 
53
53
  /**
54
- * @param urlConfig - The base URL of the Wroom app.
54
+ * @param configuration - Global object containing the different configuration
55
+ * required to setup the different clients.
55
56
  * @param credentials - Authentication credentials (email and password)
56
57
  */
57
- constructor(
58
- urlConfig: UrlConfig | string,
59
- private readonly credentials: Credentials,
60
- ) {
61
- if (typeof urlConfig === "string") {
58
+ constructor(configuration: SetupConfiguration) {
59
+ this.config = {
60
+ ...configuration,
62
61
  // When a string is provided, treat it as the 'base' property
63
- urlConfig = this.inferUrls(urlConfig);
64
- }
65
- this.urls = urlConfig;
66
- this.wroomClient = new WroomClient(this.urls.baseURL, this.credentials);
62
+ urlConfig:
63
+ typeof configuration.urlConfig === "string"
64
+ ? this.inferUrls(configuration.urlConfig)
65
+ : configuration.urlConfig,
66
+ };
67
+
68
+ this.wroomClient = new WroomClient(
69
+ this.config.urlConfig.baseURL,
70
+ this.config.authConfig,
71
+ );
67
72
  this.authClient = createAuthenticationApiClient(
68
- this.urls.authenticationApi,
69
- this.credentials,
73
+ this.config.urlConfig.authenticationApi,
74
+ this.config.authConfig,
75
+ );
76
+ this.manageV2Client = new ManageV2Client(
77
+ this.config.urlConfig.baseURL,
78
+ this.config.manageV2Config,
70
79
  );
71
80
  }
72
81
 
@@ -149,7 +158,7 @@ export class RepositoriesManager {
149
158
  const post = async () =>
150
159
  this.wroomClient.post(repository, "app/settings/delete", {
151
160
  confirm: repository,
152
- password: this.credentials.password,
161
+ password: this.config.authConfig.password,
153
162
  });
154
163
  const response = await post();
155
164
  if (response.status !== 200) {
@@ -183,27 +192,20 @@ export class RepositoriesManager {
183
192
  */
184
193
  getRepositoryManager(name: string): RepositoryManager {
185
194
  const customTypeClient = createCustomTypesApiClient(
186
- this.urls.customTypesApi,
195
+ this.config.urlConfig.customTypesApi,
187
196
  name,
188
197
  this.authClient,
189
198
  );
190
- const coreApiUrl = getRepositoryUrl(this.urls.baseURL, name);
199
+ const coreApiUrl = getRepositoryUrl(this.config.urlConfig.baseURL, name);
191
200
  const coreApiClient = createCoreApiClient(coreApiUrl, this.authClient);
192
201
 
193
202
  return new RepositoryManager(
194
203
  name,
195
204
  coreApiClient,
205
+ this.authClient,
196
206
  this.wroomClient,
197
207
  customTypeClient,
208
+ this.manageV2Client,
198
209
  );
199
210
  }
200
211
  }
201
-
202
- export type UrlConfig = {
203
- /** Prismic base url */
204
- baseURL: string;
205
- /** Custom types api base url */
206
- customTypesApi: string;
207
- /** Auth service api base url */
208
- authenticationApi: string;
209
- };