mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
refactored duplicate name logic, tests pass
This commit is contained in:
parent
ee5ffa432b
commit
10a110e898
5 changed files with 265 additions and 96 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
const { create } = require('../middleware/jwtToken');
|
||||||
const Folders = require('../models/folders');
|
const Folders = require('../models/folders');
|
||||||
const ObjectId = require('mongodb').ObjectId;
|
const ObjectId = require('mongodb').ObjectId;
|
||||||
const Quizzes = require('../models/quiz');
|
const Quizzes = require('../models/quiz');
|
||||||
|
|
@ -6,6 +7,7 @@ describe('Folders', () => {
|
||||||
let folders;
|
let folders;
|
||||||
let db;
|
let db;
|
||||||
let collection;
|
let collection;
|
||||||
|
let quizzes;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks(); // Clear any previous mock calls
|
jest.clearAllMocks(); // Clear any previous mock calls
|
||||||
|
|
@ -15,9 +17,11 @@ describe('Folders', () => {
|
||||||
findOne: jest.fn(),
|
findOne: jest.fn(),
|
||||||
insertOne: jest.fn(),
|
insertOne: jest.fn(),
|
||||||
find: jest.fn().mockReturnValue({ toArray: jest.fn() }), // Mock the find method
|
find: jest.fn().mockReturnValue({ toArray: jest.fn() }), // Mock the find method
|
||||||
|
deleteOne: jest.fn(),
|
||||||
|
deleteMany: jest.fn(),
|
||||||
|
updateOne: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Mock the database connection
|
// Mock the database connection
|
||||||
db = {
|
db = {
|
||||||
connect: jest.fn(),
|
connect: jest.fn(),
|
||||||
|
|
@ -71,6 +75,189 @@ describe('Folders', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// getUserFolders
|
||||||
|
describe('getUserFolders', () => {
|
||||||
|
it('should return all folders for a user', async () => {
|
||||||
|
const userId = '12345';
|
||||||
|
const userFolders = [
|
||||||
|
{ title: 'Folder 1', userId },
|
||||||
|
{ title: 'Folder 2', userId },
|
||||||
|
];
|
||||||
|
|
||||||
|
// Mock the database response
|
||||||
|
collection.find().toArray.mockResolvedValue(userFolders);
|
||||||
|
|
||||||
|
const result = await folders.getUserFolders(userId);
|
||||||
|
|
||||||
|
expect(db.connect).toHaveBeenCalled();
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('folders');
|
||||||
|
expect(collection.find).toHaveBeenCalledWith({ userId });
|
||||||
|
expect(result).toEqual(userFolders);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// getOwner
|
||||||
|
describe('getOwner', () => {
|
||||||
|
it('should return the owner of a folder', async () => {
|
||||||
|
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
||||||
|
const userId = '12345';
|
||||||
|
|
||||||
|
// Mock the database response
|
||||||
|
collection.findOne.mockResolvedValue({ userId });
|
||||||
|
|
||||||
|
const result = await folders.getOwner(folderId);
|
||||||
|
|
||||||
|
expect(db.connect).toHaveBeenCalled();
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('folders');
|
||||||
|
expect(collection.findOne).toHaveBeenCalledWith({ _id: new ObjectId(folderId) });
|
||||||
|
expect(result).toBe(userId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// write a test for getContent
|
||||||
|
describe('getContent', () => {
|
||||||
|
it('should return the content of a folder', async () => {
|
||||||
|
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
||||||
|
const content = [
|
||||||
|
{ title: 'Quiz 1', content: [] },
|
||||||
|
{ title: 'Quiz 2', content: [] },
|
||||||
|
];
|
||||||
|
|
||||||
|
// Mock the database response
|
||||||
|
collection.find().toArray.mockResolvedValue(content);
|
||||||
|
|
||||||
|
const result = await folders.getContent(folderId);
|
||||||
|
|
||||||
|
expect(db.connect).toHaveBeenCalled();
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('files');
|
||||||
|
expect(collection.find).toHaveBeenCalledWith({ folderId });
|
||||||
|
expect(result).toEqual(content);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty array if the folder has no content', async () => {
|
||||||
|
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
||||||
|
|
||||||
|
// Mock the database response
|
||||||
|
collection.find().toArray.mockResolvedValue([]);
|
||||||
|
|
||||||
|
const result = await folders.getContent(folderId);
|
||||||
|
|
||||||
|
expect(db.connect).toHaveBeenCalled();
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('files');
|
||||||
|
expect(collection.find).toHaveBeenCalledWith({ folderId });
|
||||||
|
expect(result).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// delete
|
||||||
|
describe('delete', () => {
|
||||||
|
it('should delete a folder and return true', async () => {
|
||||||
|
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
||||||
|
|
||||||
|
// Mock the database response
|
||||||
|
collection.deleteOne.mockResolvedValue({ deletedCount: 1 });
|
||||||
|
|
||||||
|
|
||||||
|
// Mock the folders.quizModel.deleteQuizzesByFolderId()
|
||||||
|
jest.spyOn(quizzes, 'deleteQuizzesByFolderId').mockResolvedValue(true);
|
||||||
|
|
||||||
|
const result = await folders.delete(folderId);
|
||||||
|
|
||||||
|
expect(db.connect).toHaveBeenCalled();
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('folders');
|
||||||
|
expect(collection.deleteOne).toHaveBeenCalledWith({ _id: new ObjectId(folderId) });
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if the folder does not exist', async () => {
|
||||||
|
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
||||||
|
|
||||||
|
// Mock the database response
|
||||||
|
collection.deleteOne.mockResolvedValue({ deletedCount: 0 });
|
||||||
|
|
||||||
|
const result = await folders.delete(folderId);
|
||||||
|
|
||||||
|
expect(db.connect).toHaveBeenCalled();
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('folders');
|
||||||
|
expect(collection.deleteOne).toHaveBeenCalledWith({ _id: new ObjectId(folderId) });
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// rename
|
||||||
|
describe('rename', () => {
|
||||||
|
it('should rename a folder and return true', async () => {
|
||||||
|
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
||||||
|
const newTitle = 'New Folder Name';
|
||||||
|
|
||||||
|
// Mock the database response
|
||||||
|
collection.updateOne.mockResolvedValue({ modifiedCount: 1 });
|
||||||
|
|
||||||
|
const result = await folders.rename(folderId, newTitle);
|
||||||
|
|
||||||
|
expect(db.connect).toHaveBeenCalled();
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('folders');
|
||||||
|
expect(collection.updateOne).toHaveBeenCalledWith({ _id: new ObjectId(folderId) }, { $set: { title: newTitle } });
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if the folder does not exist', async () => {
|
||||||
|
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
||||||
|
const newTitle = 'New Folder Name';
|
||||||
|
|
||||||
|
// Mock the database response
|
||||||
|
collection.updateOne.mockResolvedValue({ modifiedCount: 0 });
|
||||||
|
|
||||||
|
const result = await folders.rename(folderId, newTitle);
|
||||||
|
|
||||||
|
expect(db.connect).toHaveBeenCalled();
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('folders');
|
||||||
|
expect(collection.updateOne).toHaveBeenCalledWith({ _id: new ObjectId(folderId) }, { $set: { title: newTitle } });
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// duplicate
|
||||||
|
describe('duplicate', () => {
|
||||||
|
it('should duplicate a folder and return the new folder ID', async () => {
|
||||||
|
const userId = '12345';
|
||||||
|
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
||||||
|
const sourceFolder = {title: 'SourceFolder', userId: userId, content: []};
|
||||||
|
const duplicatedFolder = {title: 'SourceFolder (1)', userId: userId, created_at: expect.any(Date), content: []};
|
||||||
|
|
||||||
|
// Mock the database responses for the folder and the new folder (first one is found, second one is null)
|
||||||
|
// mock the findOne method
|
||||||
|
jest.spyOn(collection, 'findOne')
|
||||||
|
.mockResolvedValueOnce(sourceFolder) // source file exists
|
||||||
|
.mockResolvedValueOnce(null); // new name is not found
|
||||||
|
|
||||||
|
// Mock the create method
|
||||||
|
const createSpy = jest.spyOn(folders, 'create').mockResolvedValue(new ObjectId());
|
||||||
|
|
||||||
|
const result = await folders.duplicate(folderId, userId);
|
||||||
|
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('folders');
|
||||||
|
|
||||||
|
// expect create method was called
|
||||||
|
expect(createSpy).toHaveBeenCalledWith(duplicatedFolder.title, [], userId);
|
||||||
|
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the folder does not exist', async () => {
|
||||||
|
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
||||||
|
|
||||||
|
// Mock the database response for the source
|
||||||
|
collection.findOne.mockResolvedValue(null);
|
||||||
|
|
||||||
|
await expect(folders.duplicate(folderId, '54321')).rejects.toThrow(`Folder ${folderId} not found`);
|
||||||
|
|
||||||
|
// expect(db.connect).toHaveBeenCalled();
|
||||||
|
expect(db.collection).toHaveBeenCalledWith('folders');
|
||||||
|
expect(collection.findOne).toHaveBeenCalledWith({ _id: new ObjectId(folderId), userId: '54321' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('folderExists', () => {
|
describe('folderExists', () => {
|
||||||
it('should return true if folder exists', async () => {
|
it('should return true if folder exists', async () => {
|
||||||
const title = 'Test Folder';
|
const title = 'Test Folder';
|
||||||
|
|
@ -199,41 +386,6 @@ describe('Folders', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// write a test for getContent
|
|
||||||
describe('getContent', () => {
|
|
||||||
it('should return the content of a folder', async () => {
|
|
||||||
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
|
||||||
const content = [
|
|
||||||
{ title: 'Quiz 1', content: [] },
|
|
||||||
{ title: 'Quiz 2', content: [] },
|
|
||||||
];
|
|
||||||
|
|
||||||
// Mock the database response
|
|
||||||
collection.find().toArray.mockResolvedValue(content);
|
|
||||||
|
|
||||||
const result = await folders.getContent(folderId);
|
|
||||||
|
|
||||||
expect(db.connect).toHaveBeenCalled();
|
|
||||||
expect(db.collection).toHaveBeenCalledWith('files');
|
|
||||||
expect(collection.find).toHaveBeenCalledWith({ folderId });
|
|
||||||
expect(result).toEqual(content);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array if the folder has no content', async () => {
|
|
||||||
const folderId = '60c72b2f9b1d8b3a4c8e4d3b';
|
|
||||||
|
|
||||||
// Mock the database response
|
|
||||||
collection.find().toArray.mockResolvedValue([]);
|
|
||||||
|
|
||||||
const result = await folders.getContent(folderId);
|
|
||||||
|
|
||||||
expect(db.connect).toHaveBeenCalled();
|
|
||||||
expect(db.collection).toHaveBeenCalledWith('files');
|
|
||||||
expect(collection.find).toHaveBeenCalledWith({ folderId });
|
|
||||||
expect(result).toEqual([]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// write a test for getFolderById
|
// write a test for getFolderById
|
||||||
describe('getFolderById', () => {
|
describe('getFolderById', () => {
|
||||||
it('should return a folder by ID', async () => {
|
it('should return a folder by ID', async () => {
|
||||||
|
|
|
||||||
|
|
@ -261,18 +261,17 @@ describe('Quizzes', () => {
|
||||||
content: 'This is a test quiz.',
|
content: 'This is a test quiz.',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mock the response from getContent
|
|
||||||
const getContentMock = jest.spyOn(quizzes, 'getContent').mockResolvedValue(sourceQuiz);
|
|
||||||
const createMock = jest.spyOn(quizzes, 'create').mockResolvedValue(newQuizId);
|
const createMock = jest.spyOn(quizzes, 'create').mockResolvedValue(newQuizId);
|
||||||
// mock the response from quizExists
|
// mock the findOne method
|
||||||
jest.spyOn(quizzes, 'quizExists').mockResolvedValue(false);
|
jest.spyOn(collection, 'findOne')
|
||||||
|
.mockResolvedValueOnce(sourceQuiz) // source quiz exists
|
||||||
|
.mockResolvedValueOnce(null); // new name is not found
|
||||||
|
|
||||||
const result = await quizzes.duplicate(quizId, userId);
|
const result = await quizzes.duplicate(quizId, userId);
|
||||||
|
|
||||||
expect(result).toBe(newQuizId);
|
expect(result).toBe(newQuizId);
|
||||||
|
|
||||||
// Ensure mocks were called correctly
|
// Ensure mocks were called correctly
|
||||||
expect(getContentMock).toHaveBeenCalledWith(quizId);
|
|
||||||
expect(createMock).toHaveBeenCalledWith(
|
expect(createMock).toHaveBeenCalledWith(
|
||||||
sourceQuiz.title + ' (1)',
|
sourceQuiz.title + ' (1)',
|
||||||
sourceQuiz.content,
|
sourceQuiz.content,
|
||||||
|
|
@ -291,18 +290,17 @@ describe('Quizzes', () => {
|
||||||
content: 'This is a test quiz.',
|
content: 'This is a test quiz.',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mock the response from getContent
|
|
||||||
const getContentMock = jest.spyOn(quizzes, 'getContent').mockResolvedValue(sourceQuiz);
|
|
||||||
const createMock = jest.spyOn(quizzes, 'create').mockResolvedValue(newQuizId);
|
const createMock = jest.spyOn(quizzes, 'create').mockResolvedValue(newQuizId);
|
||||||
// mock the response from quizExists
|
// mock the findOne method
|
||||||
jest.spyOn(quizzes, 'quizExists').mockResolvedValueOnce(false);
|
jest.spyOn(collection, 'findOne')
|
||||||
|
.mockResolvedValueOnce(sourceQuiz) // source quiz exists
|
||||||
|
.mockResolvedValueOnce(null); // new name is not found
|
||||||
|
|
||||||
const result = await quizzes.duplicate(quizId, userId);
|
const result = await quizzes.duplicate(quizId, userId);
|
||||||
|
|
||||||
expect(result).toBe(newQuizId);
|
expect(result).toBe(newQuizId);
|
||||||
|
|
||||||
// Ensure mocks were called correctly
|
// Ensure mocks were called correctly
|
||||||
expect(getContentMock).toHaveBeenCalledWith(quizId);
|
|
||||||
expect(createMock).toHaveBeenCalledWith(
|
expect(createMock).toHaveBeenCalledWith(
|
||||||
'Test Quiz (2)',
|
'Test Quiz (2)',
|
||||||
sourceQuiz.content,
|
sourceQuiz.content,
|
||||||
|
|
@ -321,18 +319,19 @@ describe('Quizzes', () => {
|
||||||
content: 'This is a test quiz.',
|
content: 'This is a test quiz.',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mock the response from getContent
|
|
||||||
const getContentMock = jest.spyOn(quizzes, 'getContent').mockResolvedValue(sourceQuiz);
|
|
||||||
const createMock = jest.spyOn(quizzes, 'create').mockResolvedValue(newQuizId);
|
const createMock = jest.spyOn(quizzes, 'create').mockResolvedValue(newQuizId);
|
||||||
// mock the response from quizExists
|
|
||||||
jest.spyOn(quizzes, 'quizExists').mockResolvedValueOnce(true).mockResolvedValueOnce(false);
|
// mock the findOne method
|
||||||
|
jest.spyOn(collection, 'findOne')
|
||||||
|
.mockResolvedValueOnce(sourceQuiz) // source quiz exists
|
||||||
|
.mockResolvedValueOnce({ title: 'Test Quiz (2)' }) // new name collision
|
||||||
|
.mockResolvedValueOnce(null); // final new name is not found
|
||||||
|
|
||||||
const result = await quizzes.duplicate(quizId, userId);
|
const result = await quizzes.duplicate(quizId, userId);
|
||||||
|
|
||||||
expect(result).toBe(newQuizId);
|
expect(result).toBe(newQuizId);
|
||||||
|
|
||||||
// Ensure mocks were called correctly
|
// Ensure mocks were called correctly
|
||||||
expect(getContentMock).toHaveBeenCalledWith(quizId);
|
|
||||||
expect(createMock).toHaveBeenCalledWith(
|
expect(createMock).toHaveBeenCalledWith(
|
||||||
'Test Quiz (3)',
|
'Test Quiz (3)',
|
||||||
sourceQuiz.content,
|
sourceQuiz.content,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
//model
|
//model
|
||||||
const ObjectId = require('mongodb').ObjectId;
|
const ObjectId = require('mongodb').ObjectId;
|
||||||
|
const { generateUniqueTitle } = require('./utils');
|
||||||
|
|
||||||
class Folders {
|
class Folders {
|
||||||
constructor(db, quizModel) {
|
constructor(db, quizModel) {
|
||||||
|
|
@ -95,32 +96,28 @@ class Folders {
|
||||||
}
|
}
|
||||||
|
|
||||||
async duplicate(folderId, userId) {
|
async duplicate(folderId, userId) {
|
||||||
|
console.log("LOG: duplicate", folderId, userId);
|
||||||
|
const conn = this.db.getConnection();
|
||||||
|
const foldersCollection = conn.collection('folders');
|
||||||
|
|
||||||
const sourceFolder = await this.getFolderWithContent(folderId);
|
const sourceFolder = await foldersCollection.findOne({ _id: ObjectId.createFromHexString(folderId), userId: userId });
|
||||||
|
if (!sourceFolder) {
|
||||||
// Check if the new title already exists
|
throw new Error(`Folder ${folderId} not found`);
|
||||||
let newFolderTitle = sourceFolder.title + "-copie";
|
|
||||||
let counter = 1;
|
|
||||||
|
|
||||||
while (await this.folderExists(newFolderTitle, userId)) {
|
|
||||||
newFolderTitle = `${sourceFolder.title}-copie(${counter})`;
|
|
||||||
counter++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use the utility function to generate a unique title
|
||||||
|
const newFolderTitle = await generateUniqueTitle(sourceFolder.title, async (title) => {
|
||||||
|
return await foldersCollection.findOne({ title: title, userId: userId });
|
||||||
|
});
|
||||||
|
|
||||||
const newFolderId = await this.create(newFolderTitle, userId);
|
console.log(`duplicate: userId`, userId);
|
||||||
|
const newFolderId = await this.create(newFolderTitle, sourceFolder.content, userId);
|
||||||
|
|
||||||
if (!newFolderId) {
|
if (!newFolderId) {
|
||||||
throw new Error('Failed to create a duplicate folder.');
|
throw new Error('Failed to create duplicate folder');
|
||||||
}
|
|
||||||
|
|
||||||
for (const quiz of sourceFolder.content) {
|
|
||||||
const { title, content } = quiz;
|
|
||||||
await this.quizModel.create(title, content, newFolderId.toString(), userId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newFolderId;
|
return newFolderId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async folderExists(title, userId) {
|
async folderExists(title, userId) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
const { ObjectId } = require('mongodb');
|
const { ObjectId } = require('mongodb');
|
||||||
|
const { generateUniqueTitle } = require('./utils');
|
||||||
|
|
||||||
class Quiz {
|
class Quiz {
|
||||||
|
|
||||||
|
|
@ -113,41 +114,26 @@ class Quiz {
|
||||||
}
|
}
|
||||||
|
|
||||||
async duplicate(quizId, userId) {
|
async duplicate(quizId, userId) {
|
||||||
|
const conn = this.db.getConnection();
|
||||||
|
const quizCollection = conn.collection('files');
|
||||||
|
|
||||||
const sourceQuiz = await this.getContent(quizId);
|
const sourceQuiz = await quizCollection.findOne({ _id: ObjectId.createFromHexString(quizId), userId: userId });
|
||||||
if (!sourceQuiz) {
|
if (!sourceQuiz) {
|
||||||
throw new Error('Quiz not found for quizId: ' + quizId);
|
throw new Error('Quiz not found for quizId: ' + quizId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect if quiz name ends with a number in parentheses
|
// Use the utility function to generate a unique title
|
||||||
// if so, increment the number and append to the new quiz name
|
const newQuizTitle = await generateUniqueTitle(sourceQuiz.title, async (title) => {
|
||||||
let newQuizTitle;
|
return await quizCollection.findOne({ title: title, folderId: sourceQuiz.folderId, userId: userId });
|
||||||
let counter = 1;
|
});
|
||||||
|
|
||||||
if (sourceQuiz.title.match(/\(\d+\)$/)) {
|
const newQuizId = await this.create(newQuizTitle, sourceQuiz.content, sourceQuiz.folderId, userId);
|
||||||
const parts = sourceQuiz.title.split(' (');
|
|
||||||
parts[1] = parts[1].replace(')', '');
|
|
||||||
counter = parseInt(parts[1]) + 1;
|
|
||||||
newQuizTitle = `${parts[0]} (${counter})`;
|
|
||||||
} else {
|
|
||||||
newQuizTitle = `${sourceQuiz.title} (1)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Need to make sure no quiz exists with the new name, otherwise increment the counter until a unique name is found
|
|
||||||
while (await this.quizExists(newQuizTitle, userId)) {
|
|
||||||
counter++;
|
|
||||||
// take off the last number in parentheses and add it back with the new counter
|
|
||||||
newQuizTitle = newQuizTitle.replace(/\(\d+\)$/, `(${counter})`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const newQuizId = await this.create(newQuizTitle, sourceQuiz.content,sourceQuiz.folderId, userId);
|
|
||||||
|
|
||||||
if (!newQuizId) {
|
if (!newQuizId) {
|
||||||
throw new Error('Failed to create a duplicate quiz.');
|
throw new Error('Failed to create duplicate quiz');
|
||||||
}
|
}
|
||||||
|
|
||||||
return newQuizId;
|
return newQuizId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async quizExists(title, userId) {
|
async quizExists(title, userId) {
|
||||||
|
|
|
||||||
35
server/models/utils.js
Normal file
35
server/models/utils.js
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
// utils.js
|
||||||
|
async function generateUniqueTitle(baseTitle, existsCallback) {
|
||||||
|
console.log(`generateUniqueTitle(${baseTitle})`);
|
||||||
|
let newTitle = baseTitle;
|
||||||
|
let counter = 1;
|
||||||
|
|
||||||
|
const titleRegex = /(.*?)(\((\d+)\))?$/;
|
||||||
|
const match = baseTitle.match(titleRegex);
|
||||||
|
if (match) {
|
||||||
|
baseTitle = match[1].trim();
|
||||||
|
counter = match[3] ? parseInt(match[3], 10) + 1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the base title does not end with a parentheses expression, start with "(1)"
|
||||||
|
if (!match[2]) {
|
||||||
|
newTitle = `${baseTitle} (${counter})`;
|
||||||
|
} else {
|
||||||
|
// else increment the counter in the parentheses expression as a first try
|
||||||
|
newTitle = `${baseTitle} (${counter})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`first check of newTitle: ${newTitle}`);
|
||||||
|
|
||||||
|
while (await existsCallback(newTitle)) {
|
||||||
|
counter++;
|
||||||
|
newTitle = `${baseTitle} (${counter})`;
|
||||||
|
console.log(`trying newTitle: ${newTitle}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
generateUniqueTitle
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue