Skip to content

Commit 2265de2

Browse files
committed
testcase: strategy validation - added
1 parent 7ddd835 commit 2265de2

File tree

11 files changed

+185
-108
lines changed

11 files changed

+185
-108
lines changed

.github/workflows/test.yaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,17 @@ on:
88
- '**/*.ts'
99
jobs:
1010
test:
11-
runs-on: windows-latest
11+
runs-on: ubuntu-latest
12+
13+
services:
14+
ftp:
15+
image: delfer/alpine-ftp-server:latest
16+
ports:
17+
- 21:21
18+
- 21000-21010:21000-21010
19+
options: >-
20+
--name test-ftp-server
21+
--env USERS=one|1234
1222
1323
steps:
1424
- name: Checkout code

hawk.config.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ const config: ConfigurationOptions = {
88
sitemapPath: "sitemap.xml",
99
robotPath: "robot.txt",
1010
serviceAccountFile: "gserv.json",
11-
ftpCredential: {} as any,
11+
ftpCredential: {
12+
hostname: "localhost",
13+
username: "one",
14+
password: "1234",
15+
},
1216
};
1317

1418
export default config;

lib/core.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ export class Hawk {
2424
lookupPatterns: string[] = this.configurations.lookupPatterns,
2525
ignorePatterns: string[] = this.configurations.ignorePattern,
2626
prettify: boolean = false,
27-
): Promise<void> {
27+
): Promise<boolean> {
2828
const strategyLowercase: string = strategy.toLowerCase();
2929

3030
try {
3131
if (["gwebmaster", "gwebmaster2"].includes(strategyLowercase)) {
3232
/* For all types of website*/
33-
await this.#_googleWebmaster(
33+
return await this.#_googleWebmaster(
3434
lookupPatterns,
3535
ignorePatterns,
3636
prettify,
@@ -43,16 +43,18 @@ export class Hawk {
4343
);
4444

4545
/* For Bing, Yahoo, Yandex, Yep, etc */
46-
await new IndexNow(this).trigger(stateChangedRoutes);
46+
return await new IndexNow(this).trigger(stateChangedRoutes);
4747
} else if (strategyLowercase === "gindex") {
4848
const stateChangedRoutes: string[] = this.#_getstateChangedRoutes(
4949
lookupPatterns,
5050
ignorePatterns,
5151
);
5252

5353
/* For Google - Web page which has JobPosting or Livestream Broadcasting content. */
54-
await this.#googleIndex.jobMediaIndex(stateChangedRoutes);
54+
return await this.#googleIndex.jobMediaIndex(stateChangedRoutes);
5555
}
56+
57+
return false;
5658
} catch (err) {
5759
console.log("Program stopping.. reason below ⬇️", "\n", err);
5860
process.exit(1);
@@ -64,17 +66,19 @@ export class Hawk {
6466
ignorePattern: string[] = [],
6567
prettify: boolean = false,
6668
checkFeedback: boolean = false,
67-
): Promise<void> {
69+
): Promise<boolean> {
6870
await this.#_makeSitemapRobot(lookupPatterns, ignorePattern, prettify);
6971

70-
await this.#googleIndex.webmasterIndex(); //submit sitmap.xml
72+
const succces = await this.#googleIndex.webmasterIndex(); //submit sitmap.xml
7173

7274
if (checkFeedback) {
7375
/* check status */
7476
const statusMeta: SitemapMeta =
7577
await this.#googleIndex.webmasterFeedback();
7678
console.log(statusMeta);
7779
}
80+
81+
return succces;
7882
}
7983

8084
async #_makeSitemapRobot(

lib/gindex.ts

Lines changed: 82 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -70,108 +70,111 @@ export default class GoogleIndexing {
7070
}
7171
}
7272

73-
async jobMediaIndex(stateChangedRoutes: string[]) {
73+
async jobMediaIndex(stateChangedRoutes: string[]): Promise<boolean> {
7474
const callPromises: Promise<GoogleIndexResponseOptions>[] = [];
7575

7676
const jwtClient = new google.auth.JWT({
7777
keyFile: this.#serviceAccountFile,
7878
scopes: ["https://www.googleapis.com/auth/indexing"],
7979
});
8080

81-
jwtClient.authorize(async (err, tokens): Promise<void> => {
82-
if (err) {
83-
console.log(
84-
"Error while authorizing for indexing API scope " + err,
85-
);
86-
process.exit(1);
87-
}
81+
return new Promise((resolve, _reject) => {
82+
jwtClient.authorize(async (err, tokens): Promise<void> => {
83+
if (err) {
84+
console.log(
85+
"Error while authorizing for indexing API scope " + err,
86+
);
87+
process.exit(1);
88+
}
8889

89-
const accessToken: string = tokens?.access_token || "";
90+
const accessToken: string = tokens?.access_token || "";
9091

91-
stateChangedRoutes.forEach((updatedRoute) => {
92-
callPromises.push(
93-
this.#_callIndexingAPI(accessToken, updatedRoute),
94-
);
95-
});
92+
stateChangedRoutes.forEach((updatedRoute) => {
93+
callPromises.push(
94+
this.#_callIndexingAPI(accessToken, updatedRoute),
95+
);
96+
});
9697

97-
const apiResponses: GoogleIndexResponseOptions[] = await Promise.all(
98-
callPromises,
99-
);
98+
const apiResponses: GoogleIndexResponseOptions[] =
99+
await Promise.all(callPromises);
100+
101+
/* Grouping api responses */
102+
const statusGroups: Record<
103+
GoogleIndexStatusCode,
104+
GoogleIndexResponseOptions[]
105+
> = {
106+
204: [], //dummy
107+
400: [],
108+
403: [],
109+
429: [],
110+
200: [],
111+
};
100112

101-
/* Grouping api responses */
102-
const statusGroups: Record<
103-
GoogleIndexStatusCode,
104-
GoogleIndexResponseOptions[]
105-
> = {
106-
204: [], //dummy
107-
400: [],
108-
403: [],
109-
429: [],
110-
200: [],
111-
};
113+
apiResponses.forEach((response) => {
114+
if ([400, 403, 429, 200].includes(response.statusCode)) {
115+
statusGroups[response.statusCode].push(response);
116+
}
117+
});
118+
119+
if (statusGroups[200].length > 0) {
120+
console.log("\n✅ Successfully reported routes:");
112121

113-
apiResponses.forEach((response) => {
114-
if ([400, 403, 429, 200].includes(response.statusCode)) {
115-
statusGroups[response.statusCode].push(response);
122+
console.log(
123+
statusGroups[200].map((response) => response.url).join("\n"),
124+
);
116125
}
117-
});
118126

119-
if (statusGroups[200].length > 0) {
120-
console.log("\n✅ Successfully reported routes:");
127+
/* Error reports */
128+
if (
129+
statusGroups[400].length > 0 ||
130+
statusGroups[403].length > 0 ||
131+
statusGroups[429].length > 0
132+
) {
133+
const failedResponseCount =
134+
stateChangedRoutes.length - statusGroups[200].length;
121135

122-
console.log(
123-
statusGroups[200].map((response) => response.url).join("\n"),
124-
);
125-
}
126-
127-
/* Error reports */
128-
if (
129-
statusGroups[400].length > 0 ||
130-
statusGroups[403].length > 0 ||
131-
statusGroups[429].length > 0
132-
) {
133-
const failedResponseCount =
134-
stateChangedRoutes.length - statusGroups[200].length;
135-
136-
console.log(
137-
`\nGoogle response: ⚠️\t${failedResponseCount} of ${stateChangedRoutes.length} failed`,
138-
);
136+
console.log(
137+
`\nGoogle response: ⚠️\t${failedResponseCount} of ${stateChangedRoutes.length} failed`,
138+
);
139139

140-
console.log("\n###Google Indexing error reports:⬇️");
141-
if (statusGroups[400].length > 0) {
142-
console.log("\n👎🏻 BAD_REQUEST");
143-
console.log("Affected Routes:");
144-
statusGroups[400].forEach((response) => {
140+
console.log("\n###Google Indexing error reports:⬇️");
141+
if (statusGroups[400].length > 0) {
142+
console.log("\n👎🏻 BAD_REQUEST");
143+
console.log("Affected Routes:");
144+
statusGroups[400].forEach((response) => {
145+
console.log(
146+
response.url,
147+
"\t|\t",
148+
"Reason: " + response.body.error.message,
149+
);
150+
});
151+
}
152+
153+
if (statusGroups[403].length > 0) {
154+
console.log("\n🚫 FORBIDDEN - Ownership verification failed");
155+
console.log("Affected Routes:");
145156
console.log(
146-
response.url,
147-
"\t|\t",
148-
"Reason: " + response.body.error.message,
157+
statusGroups[403].map((response) => response.url).join("\n"),
149158
);
150-
});
151-
}
159+
}
152160

153-
if (statusGroups[403].length > 0) {
154-
console.log("\n🚫 FORBIDDEN - Ownership verification failed");
155-
console.log("Affected Routes:");
156-
console.log(
157-
statusGroups[403].map((response) => response.url).join("\n"),
158-
);
161+
if (statusGroups[429].length > 0) {
162+
console.log(
163+
"\n🚨 TOO_MANY_REQUESTS - Your quota is exceeding for Indexing API calls",
164+
);
165+
console.log("Affected Routes:");
166+
console.log(
167+
statusGroups[429].map((response) => response.url).join("\n"),
168+
);
169+
}
159170
}
160171

161-
if (statusGroups[429].length > 0) {
162-
console.log(
163-
"\n🚨 TOO_MANY_REQUESTS - Your quota is exceeding for Indexing API calls",
164-
);
165-
console.log("Affected Routes:");
166-
console.log(
167-
statusGroups[429].map((response) => response.url).join("\n"),
168-
);
169-
}
170-
}
172+
resolve(apiResponses.length === statusGroups[200].length);
173+
});
171174
});
172175
}
173176

174-
webmasterIndex(): Promise<void> {
177+
webmasterIndex(): Promise<boolean> {
175178
const siteUrl: string = `sc-domain:${this.#domainName}`;
176179
const sitemapURL: string = `https://${this.#domainName}/${
177180
this.#sitemapPath
@@ -233,7 +236,7 @@ export default class GoogleIndexing {
233236
submittedSitemap: sitemapAPIResponse.url,
234237
});
235238

236-
resolve();
239+
resolve(response.ok);
237240
} catch (error) {
238241
reject(`Request error: ${error}`);
239242
}

lib/indexnow.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Client as FTP } from "basic-ftp";
22
import { randomBytes } from "node:crypto";
33
import { readFileSync, rmSync, writeFileSync } from "node:fs";
4+
import { relative } from "node:path";
45
import { type Hawk } from "./core";
56
import {
67
constants,
@@ -20,7 +21,7 @@ export default class IndexNow {
2021
this.#domainName = domainName;
2122
}
2223

23-
async trigger(stateChangedRoutes: string[]): Promise<void> {
24+
async trigger(stateChangedRoutes: string[]): Promise<boolean> {
2425
const secretKey: Awaited<string> = await this.#_secretKeyManager();
2526

2627
/*Call Index now API */
@@ -56,6 +57,7 @@ export default class IndexNow {
5657
break;
5758
}
5859
console.log("\nIndexNow response: " + response);
60+
return apiResponse === 200;
5961
}
6062

6163
#_makeSecretKey(): string {
@@ -93,7 +95,10 @@ export default class IndexNow {
9395
writeFileSync(tempkeyfile, secretKey);
9496

9597
/*set secretkey as file name and store in root */
96-
const keyDestination: string = `/${secretKey}.txt`;
98+
const keyDestination: string = relative(
99+
process.cwd(),
100+
`${secretKey}.txt`,
101+
);
97102

98103
/* Upload to ftp server */
99104
const ftp: FTP = new FTP();

lib/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,14 @@ export default class Utils {
113113
});
114114

115115
/* Making path relative from root for server */
116-
const remotePath: string = "/" + sitemapPath;
116+
const remotePath: string = relative(process.cwd(), sitemapPath);
117117

118118
await ftp.uploadFrom(sitemapPath, remotePath);
119119

120120
ftp.close();
121121
return true;
122122
} catch (err) {
123+
console.log(err);
123124
return false;
124125
}
125126
}

test/main.test.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
import { chdir } from "node:process";
22
import { Hawk } from "../lib/core";
3+
import strategyValidator from "./utils/strategy-validator";
34
import validateRoutes from "./utils/validate-routes";
45
import validateSitemap from "./utils/validate-sitemap";
56

67
const hawkInstance = new Hawk();
78
const testSampleRootPath = "./test/test-sample";
89

10+
beforeAll(() => {
11+
process.env.isdev = "true"; //for strategyValidator
12+
});
13+
14+
beforeEach(() => {
15+
chdir(testSampleRootPath);
16+
});
17+
918
const cwd = process.cwd();
1019
afterEach(() => {
1120
chdir(cwd);
1221
});
1322

1423
test("Sitemap.xml validation", async () => {
15-
expect(await validateSitemap(testSampleRootPath, hawkInstance)).toBe(
16-
true,
17-
);
24+
expect(await validateSitemap(hawkInstance)).toBe(true);
1825
});
1926

2027
test("Routes validation", () => {
21-
expect(validateRoutes(testSampleRootPath, hawkInstance)).toBe(true);
28+
expect(validateRoutes(hawkInstance)).toBe(true);
29+
});
30+
31+
test("Strategy validation", async () => {
32+
expect(await strategyValidator(hawkInstance)).toBe(true);
2233
});

0 commit comments

Comments
 (0)