Repository: 8398a7/action-slack (ts)
Issue: Validate SLACK_WEBHOOK_URL
**Is your feature request related to a problem? Please describe.**

Say, a user made a typo like:

```
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK.URL }}
```

the value of `SLACK_WEBHOOK_URL` would be `null`. This results in an obscure error like:

```
Cannot read property 'replace' of null
```

**Describe the solution you'd like**

Validate that `SLACK_WEBHOOK_URL` must be a string.

**Describe alternatives you've considered**

N/A

**Additional context**

N/A

Pull request description: Improve handling of incoming webhook url
close #118 

Patch:
diff --git a/src/client.ts b/src/client.ts
index 0fe5675..a14e7c3 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -44,13 +44,13 @@ export class Client {
   private octokit: Octokit;
   private with: With;
 
-  constructor(props: With, token: string, webhookUrl?: string) {
+  constructor(props: With, token: string, webhookUrl?: string | null) {
     this.with = props;
     if (this.with.fields === '') this.with.fields = 'repo,commit';
 
     this.octokit = getOctokit(token);
 
-    if (webhookUrl === undefined) {
+    if (webhookUrl === undefined || webhookUrl === null || webhookUrl === '') {
       throw new Error('Specify secrets.SLACK_WEBHOOK_URL');
     }
     this.webhook = new IncomingWebhook(webhookUrl);


Test patch:
diff --git a/__tests__/client.test.ts b/__tests__/client.test.ts
index 871b91f..1bc02fd 100644
--- a/__tests__/client.test.ts
+++ b/__tests__/client.test.ts
@@ -9,6 +9,7 @@ import {
   getApiFixture,
   newWith,
   githubToken,
+  webhookUrl,
 } from './helper';
 
 import {
@@ -38,6 +39,33 @@ describe('8398a7/action-slack', () => {
     github.context.payload = {};
   });
 
+  describe('incoming webhook url', () => {
+    it('is returns an exception because the environment variable does not exist', () => {
+      const withParams = newWith();
+      expect(() => {
+        new Client(withParams, githubToken, process.env.NOT_FOUND_ENV);
+      }).toThrow();
+    });
+    it('is returns exception because null value', () => {
+      const withParams = newWith();
+      expect(() => {
+        new Client(withParams, githubToken, null);
+      }).toThrow();
+    });
+    it('is returns exception because undefined value', () => {
+      const withParams = newWith();
+      expect(() => {
+        new Client(withParams, githubToken, undefined);
+      }).toThrow();
+    });
+    it('is returns exception because empty string value', () => {
+      const withParams = newWith();
+      expect(() => {
+        new Client(withParams, githubToken, '');
+      }).toThrow();
+    });
+  });
+
   describe('fields', () => {
     it('is full fields', async () => {
       const withParams = {
@@ -46,7 +74,7 @@ describe('8398a7/action-slack', () => {
         fields:
           'repo,message,commit,author,job,action,eventName,ref,workflow,took',
       };
-      const client = new Client(withParams, githubToken, '');
+      const client = new Client(withParams, githubToken, webhookUrl);
       const payload = getTemplate(withParams.fields, successMsg);
       payload.attachments[0].color = 'good';
       expect(await client.prepare('')).toStrictEqual(payload);
@@ -59,7 +87,7 @@ describe('8398a7/action-slack', () => {
         ...newWith(),
         status: Success,
       };
-      const client = new Client(withParams, githubToken, '');
+      const client = new Client(withParams, githubToken, webhookUrl);
       const payload = getTemplate(withParams.fields, successMsg);
       payload.attachments[0].color = 'good';
       expect(await client.prepare('')).toStrictEqual(payload);
@@ -69,7 +97,7 @@ describe('8398a7/action-slack', () => {
         ...newWith(),
         status: Failure,
       };
-      const client = new Client(withParams, githubToken, '');
+      const client = new Client(withParams, githubToken, webhookUrl);
       const payload = getTemplate(withParams.fields, failMsg);
       payload.attachments[0].color = 'danger';
       expect(await client.prepare('')).toStrictEqual(payload);
@@ -79,7 +107,7 @@ describe('8398a7/action-slack', () => {
         ...newWith(),
         status: Cancelled,
       };
-      const client = new Client(withParams, githubToken, '');
+      const client = new Client(withParams, githubToken, webhookUrl);
       const payload = getTemplate(withParams.fields, cancelMsg);
       payload.attachments[0].color = 'warning';
       expect(await client.prepare('')).toStrictEqual(payload);
@@ -91,7 +119,7 @@ describe('8398a7/action-slack', () => {
       ...newWith(),
       status: Success,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(withParams.fields, msg);
     payload.attachments[0].color = 'good';
@@ -105,7 +133,7 @@ describe('8398a7/action-slack', () => {
       mention: 'here',
       if_mention: Failure,
     };
-    let client = new Client(withParams, githubToken, '');
+    let client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     let payload = getTemplate(withParams.fields, msg);
     payload.attachments[0].color = 'good';
@@ -113,7 +141,7 @@ describe('8398a7/action-slack', () => {
 
     withParams.mention = '';
     withParams.status = Failure;
-    client = new Client(withParams, githubToken, '');
+    client = new Client(withParams, githubToken, webhookUrl);
     payload = getTemplate(withParams.fields, msg);
     payload.attachments[0].color = 'danger';
     expect(await client.prepare(msg)).toStrictEqual(payload);
@@ -126,7 +154,7 @@ describe('8398a7/action-slack', () => {
       mention: 'here',
       if_mention: `${Failure},${Success}`,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(withParams.fields, `<!here> ${msg}`);
     payload.attachments[0].color = 'good';
@@ -140,7 +168,7 @@ describe('8398a7/action-slack', () => {
       mention: 'here',
       if_mention: Success,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(withParams.fields, `<!here> ${msg}`);
     payload.attachments[0].color = 'good';
@@ -154,7 +182,7 @@ describe('8398a7/action-slack', () => {
       mention: 'here',
       if_mention: Failure,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(withParams.fields, `<!here> ${msg}`);
     payload.attachments[0].color = 'danger';
@@ -168,7 +196,7 @@ describe('8398a7/action-slack', () => {
       mention: 'here',
       if_mention: Cancelled,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(withParams.fields, `<!here> ${msg}`);
     payload.attachments[0].color = 'warning';
@@ -182,7 +210,7 @@ describe('8398a7/action-slack', () => {
       mention: 'here',
       if_mention: Always,
     };
-    let client = new Client(withParams, githubToken, '');
+    let client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     let payload = getTemplate(withParams.fields, `<!here> ${msg}`);
     payload.attachments[0].color = 'good';
@@ -191,13 +219,13 @@ describe('8398a7/action-slack', () => {
     payload = getTemplate(withParams.fields, `<!here> ${msg}`);
     payload.attachments[0].color = 'danger';
     withParams.status = Failure;
-    client = new Client(withParams, githubToken, '');
+    client = new Client(withParams, githubToken, webhookUrl);
     expect(await client.prepare(msg)).toStrictEqual(payload);
 
     payload = getTemplate(withParams.fields, `<!here> ${msg}`);
     payload.attachments[0].color = 'warning';
     withParams.status = Cancelled;
-    client = new Client(withParams, githubToken, '');
+    client = new Client(withParams, githubToken, webhookUrl);
     expect(await client.prepare(msg)).toStrictEqual(payload);
   });
 
@@ -208,7 +236,7 @@ describe('8398a7/action-slack', () => {
       mention: 'user_id',
       if_mention: Success,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(withParams.fields, `<@user_id> ${msg}`);
     payload.attachments[0].color = 'good';
@@ -222,7 +250,7 @@ describe('8398a7/action-slack', () => {
       mention: 'here',
       if_mention: Success,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(withParams.fields, `<!here> ${msg}`);
     payload.attachments[0].color = 'good';
@@ -236,7 +264,7 @@ describe('8398a7/action-slack', () => {
       mention: 'channel',
       if_mention: Success,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(withParams.fields, `<!channel> ${msg}`);
     payload.attachments[0].color = 'good';
@@ -250,7 +278,7 @@ describe('8398a7/action-slack', () => {
       mention: 'subteam^user_group_id',
       if_mention: Success,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(
       withParams.fields,
@@ -267,7 +295,7 @@ describe('8398a7/action-slack', () => {
       mention: 'subteam^user_group_id,subteam^user_group_id2',
       if_mention: Success,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(
       withParams.fields,
@@ -284,7 +312,7 @@ describe('8398a7/action-slack', () => {
       mention: 'user_id,user_id2',
       if_mention: Success,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(
       withParams.fields,
@@ -301,7 +329,7 @@ describe('8398a7/action-slack', () => {
       mention: 'user_id,subteam^user_group_id',
       if_mention: Success,
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(
       withParams.fields,
@@ -318,7 +346,7 @@ describe('8398a7/action-slack', () => {
       mention: 'user_id, user_id2',
       if_mention: Success,
     };
-    let client = new Client(withParams, githubToken, '');
+    let client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'hello';
 
     let payload = getTemplate(
@@ -334,7 +362,7 @@ describe('8398a7/action-slack', () => {
       ...newWith(),
       status: Success,
     };
-    let client = new Client(withParams, githubToken, '');
+    let client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'hello';
 
     // for success
@@ -344,14 +372,14 @@ describe('8398a7/action-slack', () => {
 
     // for cancel
     withParams.status = Cancelled;
-    client = new Client(withParams, githubToken, '');
+    client = new Client(withParams, githubToken, webhookUrl);
     payload = getTemplate(withParams.fields, msg);
     payload.attachments[0].color = 'warning';
     expect(await client.prepare(msg)).toStrictEqual(payload);
 
     // for fail
     withParams.status = Failure;
-    client = new Client(withParams, githubToken, '');
+    client = new Client(withParams, githubToken, webhookUrl);
     payload = getTemplate(withParams.fields, msg);
     payload.attachments[0].color = 'danger';
     expect(await client.prepare(msg)).toStrictEqual(payload);
@@ -391,7 +419,7 @@ describe('8398a7/action-slack', () => {
         status: 'custom',
         fields: 'all',
       };
-      const client = new Client(withParams, githubToken, '');
+      const client = new Client(withParams, githubToken, webhookUrl);
       expect(
         await client.custom(`{
           text: \`\${process.env.AS_WORKFLOW}
@@ -409,7 +437,7 @@ describe('8398a7/action-slack', () => {
         ...newWith(),
         status: 'custom',
       };
-      const client = new Client(withParams, githubToken, '');
+      const client = new Client(withParams, githubToken, webhookUrl);
       expect(() => client.injectColor()).toThrow();
     });
   });
@@ -419,7 +447,7 @@ describe('8398a7/action-slack', () => {
         ...newWith(),
         status: 'custom',
       };
-      const client = new Client(withParams, githubToken, '');
+      const client = new Client(withParams, githubToken, webhookUrl);
       expect(() => client.injectText('')).toThrow();
     });
   });
@@ -431,7 +459,7 @@ describe('8398a7/action-slack', () => {
         mention: 'test1,test2, here',
         if_mention: Success,
       };
-      const client = new Client(withParams, githubToken, '');
+      const client = new Client(withParams, githubToken, webhookUrl);
       expect(client.mentionText(Success)).toStrictEqual(
         '<@test1> <@test2> <!here> ',
       );
diff --git a/__tests__/customJobName.test.ts b/__tests__/customJobName.test.ts
index bbc58c2..8fd5209 100644
--- a/__tests__/customJobName.test.ts
+++ b/__tests__/customJobName.test.ts
@@ -9,6 +9,7 @@ import {
   setupNockCommit,
   setupNockJobs,
   successMsg,
+  webhookUrl,
 } from './helper';
 import { Client, With, Success } from '../src/client';
 
@@ -40,7 +41,7 @@ describe('job_name', () => {
       fields: 'job,took',
       job_name: 'Custom Job',
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     expect(await client.prepare('')).toStrictEqual({
       text: successMsg,
       attachments: [
diff --git a/__tests__/helper.ts b/__tests__/helper.ts
index 42e17dd..892312c 100644
--- a/__tests__/helper.ts
+++ b/__tests__/helper.ts
@@ -6,6 +6,7 @@ import { FieldFactory } from '../src/fields';
 import { getOctokit } from '@actions/github';
 
 export const githubToken = 'github-token';
+export const webhookUrl = 'https://hooks.slack.com/services/xxx';
 
 export const getTemplate: any = (
   fields: string,
diff --git a/__tests__/incorrectMatrix.test.ts b/__tests__/incorrectMatrix.test.ts
index 1270616..8e858a1 100644
--- a/__tests__/incorrectMatrix.test.ts
+++ b/__tests__/incorrectMatrix.test.ts
@@ -9,6 +9,7 @@ import {
   setupNockCommit,
   setupNockJobs,
   successMsg,
+  webhookUrl,
 } from './helper';
 import { Client, With, Success } from '../src/client';
 
@@ -39,7 +40,7 @@ describe('MATRIX_CONTEXT', () => {
       status: Success,
       fields: 'job,took',
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     expect(await client.prepare('')).toStrictEqual({
       text: successMsg,
       attachments: [
diff --git a/__tests__/matrix.test.ts b/__tests__/matrix.test.ts
index dce4b2e..730913d 100644
--- a/__tests__/matrix.test.ts
+++ b/__tests__/matrix.test.ts
@@ -9,6 +9,7 @@ import {
   setupNockCommit,
   setupNockJobs,
   successMsg,
+  webhookUrl,
 } from './helper';
 import { Client, With, Success } from '../src/client';
 
@@ -39,7 +40,7 @@ describe('MATRIX_CONTEXT', () => {
       status: Success,
       fields: 'job,took',
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     expect(await client.prepare('')).toStrictEqual({
       text: successMsg,
       attachments: [
diff --git a/__tests__/pull_request.test.ts b/__tests__/pull_request.test.ts
index 046a589..eb132a7 100644
--- a/__tests__/pull_request.test.ts
+++ b/__tests__/pull_request.test.ts
@@ -2,7 +2,13 @@ import nock from 'nock';
 
 process.env.GITHUB_EVENT_NAME = 'pull_request';
 
-import { setupNockCommit, getTemplate, newWith, githubToken } from './helper';
+import {
+  setupNockCommit,
+  getTemplate,
+  newWith,
+  githubToken,
+  webhookUrl,
+} from './helper';
 import { Client, With, Success } from '../src/client';
 
 beforeAll(() => {
@@ -33,7 +39,7 @@ describe('pull request event', () => {
       if_mention: Success,
       fields: 'action',
     };
-    const client = new Client(withParams, githubToken, '');
+    const client = new Client(withParams, githubToken, webhookUrl);
     const msg = 'mention test';
     const payload = getTemplate(withParams.fields, `<@user_id> ${msg}`, sha);
     payload.attachments[0].color = 'good';