sr-npm 1.7.820 → 1.7.821

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.
@@ -1,4 +1,4 @@
1
- const { COLLECTIONS } = require('./collectionConsts');
1
+ const { COLLECTIONS,JOBS_COLLECTION_FIELDS } = require('./collectionConsts');
2
2
  const { items: wixData } = require('@wix/data');
3
3
 
4
4
 
@@ -18,7 +18,11 @@ async function getPositionsByField(field, value) {
18
18
  .then(result => result.items);
19
19
  }
20
20
 
21
- module.exports = {
22
- getAllPositions,
23
- getPositionsByField,
24
- };
21
+ async function getPositionWithMultiRefField(jobId)
22
+ {
23
+ return wixData
24
+ .queryReferenced(COLLECTIONS.JOBS,jobId,JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES)
25
+ .then(result => result.items);
26
+ }
27
+
28
+ module.exports = { getAllPositions, getPositionsByField, getPositionWithMultiRefField };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sr-npm",
3
- "version": "1.7.820",
3
+ "version": "1.7.821",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,20 +1,41 @@
1
1
  const { query } = require("wix-location-frontend");
2
+ const { getPositionWithMultiRefField } = require('../backend/queries');
3
+ const { COLLECTIONS,JOBS_COLLECTION_FIELDS,CUSTOM_FIELDS_COLLECTION_FIELDS } = require('../backend/collectionConsts');
4
+ const { items: wixData } = require('@wix/data');
5
+ const { location } = require("@wix/site-location");
2
6
  const {
3
7
  htmlToText,
4
8
  appendQueryParams
5
9
  } = require('../public/utils');
6
10
 
7
11
 
12
+
13
+
8
14
  async function positionPageOnReady(_$w) {
9
15
 
10
16
  await bind(_$w);
17
+
18
+
11
19
 
12
20
  }
13
21
 
22
+ async function getCategoryValueId(customFields) {
23
+ const categoryCustomField=await wixData.query(COLLECTIONS.CUSTOM_FIELDS).eq(CUSTOM_FIELDS_COLLECTION_FIELDS.TITLE,"Category").find().then(result => result.items[0]);
24
+ for(const field of customFields) {
25
+ if(field.customField===categoryCustomField._id) {
26
+ return field._id;
27
+
28
+ }
29
+ }
30
+ }
31
+
32
+
14
33
  async function bind(_$w) {
15
34
  _$w('#datasetJobsItem').onReady(async () => {
16
35
 
17
36
  const item = await _$w('#datasetJobsItem').getCurrentItem();
37
+ const multiRefField=await getPositionWithMultiRefField(item._id);
38
+ const categoryValueId=await getCategoryValueId(multiRefField);
18
39
 
19
40
  handleReferFriendButton(_$w,item);
20
41
 
@@ -24,18 +45,46 @@ const {
24
45
  _$w('#responsibilitiesText').text = htmlToText(item.jobDescription.jobDescription.text);
25
46
  _$w('#qualificationsText').text = htmlToText(item.jobDescription.qualifications.text);
26
47
  _$w('#relatedJobsTitleText').text = `More ${item.department} Positions`;
48
+ if(_$w('#additionalInfoText'))
49
+ {
50
+ _$w('#additionalInfoText').text = htmlToText(item.jobDescription.additionalInformation.text);
51
+ }
52
+ if(_$w('#relatedJobsRepNoDepartment')) // when there is no department, we filter based on category
53
+ {
54
+ const relatedJobs=await getRelatedJobs(categoryValueId,item._id);
55
+ _$w('#relatedJobsRepNoDepartment').onItemReady(($item, itemData) => {
56
+ $item('#relatedJobTitle').text = itemData.title;
57
+ $item('#relatedJobLocation').text = itemData.location.fullLocation;
58
+ // $item('#relatedJobTitle').onClick(async () => {
59
+ // await location.to(itemData["link-jobs-title"]);
60
+ // });
61
+ });
62
+ _$w('#relatedJobsRepNoDepartment').data = relatedJobs
63
+ _$w('#relatedJobsNoDepartmentItem').onClick((event) => {
64
+ const data = _$w("#relatedJobsRepNoDepartment").data;
65
+ const clickedItemData = data.find(
66
+ (item) => item._id === event.context.itemId,
67
+ );
68
+ location.to(clickedItemData["link-jobs-title"]);
69
+ });
70
+
71
+ }
27
72
  });
28
73
 
74
+ if(_$w('#relatedJobsDataset') && _$w('#relatedJobsDataset').length>0)
75
+ {
29
76
  _$w('#relatedJobsDataset').onReady(() => {
30
77
  const count = _$w('#relatedJobsDataset').getTotalCount();
31
78
  if(!count){
32
79
  _$w('#relatedJobsSection').collapse();
33
80
  }
34
81
  });
82
+ }
83
+
35
84
  }
36
85
 
37
86
  function handleReferFriendButton(_$w,item) {
38
- if(!item.referFriendLink){
87
+ if(!item.referFriendLink && _$w('#referFriendButton')){
39
88
  console.log("hiding referFriendButton");
40
89
  _$w('#referFriendButton').hide();
41
90
  }
@@ -47,6 +96,11 @@ const {
47
96
  _$w('#applyButton').link=url; //so it can be clicked
48
97
  }
49
98
 
99
+ async function getRelatedJobs(categoryValueId,itemId) {
100
+ const relatedJobs=await wixData.query(COLLECTIONS.JOBS).include(JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES).hasSome(JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES,[categoryValueId]).ne("_id",itemId).find();
101
+ return relatedJobs.items;
102
+ }
103
+
50
104
  module.exports = {
51
105
  positionPageOnReady,
52
106
  };
@@ -120,6 +120,67 @@ class MockJobBuilder {
120
120
  return this;
121
121
  }
122
122
 
123
+ withMultiRefCustomValues(categoryIds) {
124
+ this.jobData.multiRefJobsCustomValues = categoryIds;
125
+ return this;
126
+ }
127
+
128
+ withCategory(categoryId) {
129
+ if (!this.jobData.multiRefJobsCustomValues) {
130
+ this.jobData.multiRefJobsCustomValues = [];
131
+ }
132
+ this.jobData.multiRefJobsCustomValues.push(categoryId);
133
+ return this;
134
+ }
135
+
136
+ withDepartment(department) {
137
+ this.jobData.department = department;
138
+ return this;
139
+ }
140
+
141
+ withJobDescription(companyDesc, jobDesc, qualifications, additionalInfo = null) {
142
+ this.jobData.jobDescription = {
143
+ companyDescription: { text: companyDesc },
144
+ jobDescription: { text: jobDesc },
145
+ qualifications: { text: qualifications }
146
+ };
147
+ if (additionalInfo) {
148
+ this.jobData.jobDescription.additionalInformation = { text: additionalInfo };
149
+ }
150
+ return this;
151
+ }
152
+
153
+ withApplyLink(link) {
154
+ this.jobData.applyLink = link;
155
+ return this;
156
+ }
157
+
158
+ withLinkJobsTitle(link) {
159
+ this.jobData['link-jobs-title'] = link;
160
+ return this;
161
+ }
162
+
163
+ forPositionPage() {
164
+ if (!this.jobData._id) {
165
+ this.jobData._id = this.generateId();
166
+ }
167
+ if (!this.jobData.department) {
168
+ this.jobData.department = 'Technology';
169
+ }
170
+ if (!this.jobData.jobDescription) {
171
+ this.withJobDescription(
172
+ '<p>Great company to work for</p>',
173
+ '<p>You will build awesome stuff</p>',
174
+ '<p>Must know how to code</p>',
175
+ '<p>Additional info here</p>'
176
+ );
177
+ }
178
+ if (!this.jobData.applyLink) {
179
+ this.jobData.applyLink = `https://apply.com/${this.jobData.id}`;
180
+ }
181
+ return this;
182
+ }
183
+
123
184
  asRemote() {
124
185
  this.jobData.location.remote = true;
125
186
  return this;
@@ -176,6 +237,38 @@ class MockJobBuilder {
176
237
  }
177
238
  return jobs;
178
239
  }
240
+
241
+ static createJobsWithSameCategory(categoryId, count = 3) {
242
+ const jobs = [];
243
+ const titles = [
244
+ 'Frontend Developer', 'Backend Developer', 'Full Stack Engineer',
245
+ 'DevOps Engineer', 'QA Engineer', 'Data Scientist',
246
+ 'Product Manager', 'UX Designer', 'System Architect'
247
+ ];
248
+ const cities = [
249
+ { city: 'Auckland', region: 'Auckland Region' },
250
+ { city: 'Wellington', region: 'Wellington Region' },
251
+ { city: 'Christchurch', region: 'Canterbury Region' },
252
+ { city: 'Hamilton', region: 'Waikato Region' },
253
+ { city: 'Dunedin', region: 'Otago Region' }
254
+ ];
255
+
256
+ for (let i = 0; i < count; i++) {
257
+ const randomTitle = titles[Math.floor(Math.random() * titles.length)];
258
+ const randomCity = cities[Math.floor(Math.random() * cities.length)];
259
+
260
+ jobs.push(
261
+ new MockJobBuilder()
262
+ .withTitle(`${randomTitle} ${i + 1}`)
263
+ .withCity(randomCity.city, randomCity.region)
264
+ .withCategory(categoryId)
265
+ .withLinkJobsTitle(`/jobs/${randomTitle.toLowerCase().replace(/\s+/g, '-')}-${i + 1}`)
266
+ .forPositionPage()
267
+ .build()
268
+ );
269
+ }
270
+ return jobs;
271
+ }
179
272
  }
180
273
 
181
274
  module.exports = MockJobBuilder;
@@ -0,0 +1,139 @@
1
+ const MockJobBuilder = require('./mockJobBuilder');
2
+
3
+ // Create mocks before importing
4
+ const mockQueryChain = {
5
+ eq: jest.fn().mockReturnThis(),
6
+ find: jest.fn(),
7
+ include: jest.fn().mockReturnThis(),
8
+ hasSome: jest.fn().mockReturnThis(),
9
+ ne: jest.fn().mockReturnThis(),
10
+ limit: jest.fn().mockReturnThis(),
11
+ then: jest.fn()
12
+ };
13
+
14
+ const mockWixData = {
15
+ query: jest.fn(() => mockQueryChain),
16
+ queryReferenced: jest.fn()
17
+ };
18
+
19
+ jest.mock('wix-location-frontend', () => ({
20
+ query: {}
21
+ }), { virtual: true });
22
+ jest.mock('@wix/data', () => ({
23
+ items: mockWixData
24
+ }));
25
+ jest.mock('@wix/site-location', () => ({
26
+ location: {
27
+ to: jest.fn()
28
+ }
29
+ }));
30
+
31
+ // Mock the backend queries module as well
32
+ jest.mock('../backend/queries', () => ({
33
+ getPositionWithMultiRefField: jest.fn()
34
+ }));
35
+
36
+ // Mock utils
37
+ jest.mock('../public/utils', () => ({
38
+ htmlToText: jest.fn((text) => text.replace(/<[^>]*>/g, '')),
39
+ appendQueryParams: jest.fn((url) => url)
40
+ }));
41
+
42
+ const { positionPageOnReady } = require('../pages/positionPage');
43
+ const { getPositionWithMultiRefField } = require('../backend/queries');
44
+
45
+
46
+ describe('related jobs show jobs with the same category value test', () => {
47
+ let mockW;
48
+ let mockRealtedJobsRepeater;
49
+
50
+ beforeEach(() => {
51
+ // Create a proper repeater mock that allows data to be set
52
+ mockRealtedJobsRepeater = {
53
+ data: null,
54
+ onItemReady: jest.fn()
55
+ };
56
+ });
57
+
58
+ it('should show related jobs with the same category value', async () => {
59
+ const CATEGORY_FIELD_ID = `category-field-${Date.now()}`;
60
+ const TECH_CATEGORY_VALUE_ID = `tech-category-${Math.floor(Math.random() * 10000)}`;
61
+
62
+ // Create current job using MockJobBuilder with random data
63
+ const currentJob = new MockJobBuilder()
64
+ .withTitle('Senior Developer')
65
+ .withDepartment('Technology')
66
+ .withCategory(TECH_CATEGORY_VALUE_ID)
67
+ .forPositionPage()
68
+ .build();
69
+
70
+ // Create 0-5 related jobs with same category using random data (including case with 0 related jobs)
71
+ const relatedJobsCount = Math.floor(Math.random() * 6); // 0-5 jobs
72
+ const relatedJobs = MockJobBuilder.createJobsWithSameCategory(
73
+ TECH_CATEGORY_VALUE_ID,
74
+ relatedJobsCount
75
+ );
76
+
77
+ // Current job's custom values (Tech category)
78
+ const currentJobCustomValues = [
79
+ { _id: TECH_CATEGORY_VALUE_ID, customField: CATEGORY_FIELD_ID, title: 'Technology' }
80
+ ];
81
+
82
+ const categoryCustomField = {
83
+ _id: CATEGORY_FIELD_ID,
84
+ title: 'Category'
85
+ };
86
+
87
+ // Setup mocks - capture the onReady callback so we can await it
88
+ let datasetReadyCallback;
89
+ const mockDataset = {
90
+ onReady: jest.fn((callback) => {
91
+ datasetReadyCallback = callback;
92
+ }),
93
+ getCurrentItem: jest.fn().mockResolvedValue(currentJob)
94
+ };
95
+
96
+ mockW = jest.fn((selector) => {
97
+ const mocks = {
98
+ '#datasetJobsItem': mockDataset,
99
+ '#relatedJobsRepNoDepartment': mockRealtedJobsRepeater,
100
+ '#companyDescriptionText': { text: '' },
101
+ '#responsibilitiesText': { text: '' },
102
+ '#qualificationsText': { text: '' },
103
+ '#relatedJobsTitleText': { text: '' },
104
+ '#additionalInfoText': { text: '' },
105
+ '#applyButton': { target: '', link: '' }
106
+ };
107
+ return mocks[selector] || { text: '', hide: jest.fn() };
108
+ });
109
+
110
+ getPositionWithMultiRefField.mockResolvedValue(currentJobCustomValues);
111
+
112
+ mockQueryChain.find.mockImplementation(() => {
113
+ const queryArg = mockWixData.query.mock.calls[mockWixData.query.mock.calls.length - 1][0];
114
+ if (queryArg === 'CustomFields') {
115
+ return Promise.resolve({ items: [categoryCustomField] });
116
+ }
117
+ return Promise.resolve({ items: relatedJobs });
118
+ });
119
+
120
+ // Run the page function (sets up the onReady callback)
121
+ await positionPageOnReady(mockW);
122
+
123
+ // Now execute the dataset onReady callback and wait for it
124
+ await datasetReadyCallback();
125
+
126
+ // Verify the repeater got populated with related jobs
127
+ expect(mockRealtedJobsRepeater.data).not.toBeNull();
128
+ expect(mockRealtedJobsRepeater.data).toHaveLength(relatedJobsCount);
129
+
130
+ // Verify all related jobs have the same category as current job
131
+ const allHaveSameCategory = mockRealtedJobsRepeater.data.every(job =>
132
+ job.multiRefJobsCustomValues &&
133
+ job.multiRefJobsCustomValues.includes(TECH_CATEGORY_VALUE_ID)
134
+ );
135
+ expect(allHaveSameCategory).toBe(true);
136
+ });
137
+
138
+ });
139
+