googleformsubmitter 1.1.1 → 1.1.2

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,33 @@
1
+ name: Publish main branch
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ permissions:
9
+ id-token: write # Required for OIDC https://docs.npmjs.com/trusted-publishers
10
+ contents: write # Required for pushing tags
11
+
12
+ jobs:
13
+ publish-main:
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: 20
21
+ registry-url: https://registry.npmjs.org/
22
+ # Ensure npm 11.5.1 or later is installed
23
+ - run: npm install -g npm@latest
24
+ - name: Bump version
25
+ run: |
26
+ git config --global user.name "github-actions"
27
+ git config --global user.email "github-actions@github.com"
28
+ npm version patch
29
+ - name: Publish to NPM
30
+ run: npm publish --access public
31
+ - name: Commit and push
32
+ run: |
33
+ git push --follow-tags
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "googleformsubmitter",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "module": "src/index.ts",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
7
7
  "type": "module",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/iconicompany/googleformsubmitter.git"
11
+ },
8
12
  "scripts": {
9
13
  "test": "bun test",
10
14
  "lint": "oxlint",
@@ -84,7 +84,7 @@ describe('GoogleFormSubmitter E2E Integration', () => {
84
84
 
85
85
  const formUrl = 'https://docs.google.com/forms/d/e/1FAIpQLSc1aiEAhxWCMSNjZ1asGDtXV_mT8vTiJRquiqfdjsoMkKT9tw/viewform';
86
86
  const credentialsPath = path.join(__dirname, '..', '..', 'imatching', '.data', 'credentials.json');
87
- const tokenPath = path.join(__dirname, '..', '..', 'imatching', '.data', 'forms-auth.json');
87
+ const tokenPath = path.join(__dirname, '..', '..', 'imatching', '.data', 'gdrive-auth.json');
88
88
 
89
89
  submitter = new GoogleFormSubmitter({
90
90
  formUrl,
@@ -103,10 +103,10 @@ describe('GoogleFormSubmitter E2E Integration', () => {
103
103
  test('should dynamically resolve fields, upload file, and submit successfully', async () => {
104
104
  const candidateData = {
105
105
  requestId: '910',
106
- fullName: 'Багманов Алмаз (Схема)',
106
+ fullName: 'Тестов Тест (Схема)',
107
107
  birthDate: '1996-07-03',
108
108
  grade: 'Middle',
109
- location: 'Россия, Набережные Челны',
109
+ location: 'Россия, Москва',
110
110
  rate: '2000',
111
111
  nds: 'Нет',
112
112
  exitDate: 'через 21 дней',
@@ -114,7 +114,7 @@ describe('GoogleFormSubmitter E2E Integration', () => {
114
114
  inStaff: 'Да',
115
115
  cvFile: {
116
116
  buffer: Buffer.from('mock cv file contents for integration test'),
117
- filename: 'cv_Багманов_Алмаз.docx',
117
+ filename: 'cv_Тестов_Тест.docx',
118
118
  mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
119
119
  },
120
120
  company: 'Iconicompany',
@@ -130,7 +130,7 @@ describe('GoogleFormSubmitter E2E Integration', () => {
130
130
  expect(result1.statusCode).toBe(200);
131
131
 
132
132
  console.log('\n--- SECOND RUN: Submitting instantly using cache ---');
133
- candidateData.fullName = 'Багманов Алмаз (Схема-Кэш)';
133
+ candidateData.fullName = 'Тестов Тест (Схема-Кэш)';
134
134
  const result2 = await submitter.submit(candidateData);
135
135
  console.log('Result 2 Fields Submitted:', JSON.stringify(result2.fieldsSubmitted, null, 2));
136
136
 
@@ -138,3 +138,36 @@ describe('GoogleFormSubmitter E2E Integration', () => {
138
138
  expect(result2.statusCode).toBe(200);
139
139
  }, 45000); // 45 seconds timeout
140
140
  });
141
+
142
+ describe('GoogleFormSubmitter.formatFields Unit Tests', () => {
143
+ test('should format simple text and choice fields correctly', () => {
144
+ const fields = {
145
+ 'Номер запроса': '917',
146
+ 'ФИО (полностью)': 'Иванов Иван Иванович',
147
+ 'Грейд': 'middle'
148
+ };
149
+ const formatted = GoogleFormSubmitter.formatFields(fields);
150
+ expect(formatted).toContain('• Номер запроса: 917');
151
+ expect(formatted).toContain('• ФИО (полностью): Иванов Иван Иванович');
152
+ expect(formatted).toContain('• Грейд: middle');
153
+ });
154
+
155
+ test('should parse nested CV array and display only the filename', () => {
156
+ const fields = {
157
+ 'CV (файл)': '[[["1Nrch5iArW-Gx-Vz4x9YlAM6FuhI5tEtt","cv_Иванов_Иван_Иванович.docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"]]]'
158
+ };
159
+ const formatted = GoogleFormSubmitter.formatFields(fields);
160
+ expect(formatted).toBe('• CV (файл): cv_Иванов_Иван_Иванович.docx');
161
+ });
162
+
163
+ test('should handle empty/null/undefined values gracefully', () => {
164
+ const fields = {
165
+ 'Комментарий': null,
166
+ 'Ближайший планируемый отпуск': undefined
167
+ };
168
+ const formatted = GoogleFormSubmitter.formatFields(fields);
169
+ expect(formatted).toContain('• Комментарий: —');
170
+ expect(formatted).toContain('• Ближайший планируемый отпуск: —');
171
+ });
172
+ });
173
+
@@ -337,4 +337,32 @@ export class GoogleFormSubmitter {
337
337
  await browser.close();
338
338
  }
339
339
  }
340
+
341
+ /**
342
+ * Helper to format submitted fields or raw payload into a clean, human-readable list.
343
+ */
344
+ public static formatFields(fields: Record<string, any>): string {
345
+ const formatValue = (val: any): string => {
346
+ if (typeof val === 'string') {
347
+ if (val.startsWith('[[[') && val.endsWith(']]]')) {
348
+ try {
349
+ const parsed = JSON.parse(val);
350
+ if (Array.isArray(parsed) && parsed[0]?.[0]?.[1]) {
351
+ return parsed[0][0][1];
352
+ }
353
+ } catch {}
354
+ }
355
+ return val;
356
+ }
357
+ if (val === null || val === undefined) {
358
+ return '—';
359
+ }
360
+ return String(val);
361
+ };
362
+
363
+ return Object.entries(fields)
364
+ .map(([key, val]) => `• ${key}: ${formatValue(val)}`)
365
+ .join('\n');
366
+ }
340
367
  }
368
+
@@ -1,16 +0,0 @@
1
- {
2
- "requestId": "1876174487",
3
- "fullName": "1192130047",
4
- "birthDate": "1354328376",
5
- "grade": "1867801269",
6
- "location": "1504377681",
7
- "rate": "282114114",
8
- "nds": "1347448341",
9
- "exitDate": "1161802420",
10
- "vacation": "1977793041",
11
- "inStaff": "447126466",
12
- "cvFile": "1595274093",
13
- "company": "553187985",
14
- "checklist": "1954006978",
15
- "comment": "998553124"
16
- }
package/CLAUDE.md DELETED
@@ -1,106 +0,0 @@
1
-
2
- Default to using Bun instead of Node.js.
3
-
4
- - Use `bun <file>` instead of `node <file>` or `ts-node <file>`
5
- - Use `bun test` instead of `jest` or `vitest`
6
- - Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
7
- - Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
8
- - Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
9
- - Use `bunx <package> <command>` instead of `npx <package> <command>`
10
- - Bun automatically loads .env, so don't use dotenv.
11
-
12
- ## APIs
13
-
14
- - `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
15
- - `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
16
- - `Bun.redis` for Redis. Don't use `ioredis`.
17
- - `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
18
- - `WebSocket` is built-in. Don't use `ws`.
19
- - Prefer `Bun.file` over `node:fs`'s readFile/writeFile
20
- - Bun.$`ls` instead of execa.
21
-
22
- ## Testing
23
-
24
- Use `bun test` to run tests.
25
-
26
- ```ts#index.test.ts
27
- import { test, expect } from "bun:test";
28
-
29
- test("hello world", () => {
30
- expect(1).toBe(1);
31
- });
32
- ```
33
-
34
- ## Frontend
35
-
36
- Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
37
-
38
- Server:
39
-
40
- ```ts#index.ts
41
- import index from "./index.html"
42
-
43
- Bun.serve({
44
- routes: {
45
- "/": index,
46
- "/api/users/:id": {
47
- GET: (req) => {
48
- return new Response(JSON.stringify({ id: req.params.id }));
49
- },
50
- },
51
- },
52
- // optional websocket support
53
- websocket: {
54
- open: (ws) => {
55
- ws.send("Hello, world!");
56
- },
57
- message: (ws, message) => {
58
- ws.send(message);
59
- },
60
- close: (ws) => {
61
- // handle close
62
- }
63
- },
64
- development: {
65
- hmr: true,
66
- console: true,
67
- }
68
- })
69
- ```
70
-
71
- HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
72
-
73
- ```html#index.html
74
- <html>
75
- <body>
76
- <h1>Hello, world!</h1>
77
- <script type="module" src="./frontend.tsx"></script>
78
- </body>
79
- </html>
80
- ```
81
-
82
- With the following `frontend.tsx`:
83
-
84
- ```tsx#frontend.tsx
85
- import React from "react";
86
- import { createRoot } from "react-dom/client";
87
-
88
- // import .css files directly and it works
89
- import './index.css';
90
-
91
- const root = createRoot(document.body);
92
-
93
- export default function Frontend() {
94
- return <h1>Hello, world!</h1>;
95
- }
96
-
97
- root.render(<Frontend />);
98
- ```
99
-
100
- Then, run index.ts
101
-
102
- ```sh
103
- bun --hot ./index.ts
104
- ```
105
-
106
- For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.