Skip to content

Commit

Permalink
v0.1.4 add N/file mock, fix some bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
emorris00 committed Nov 3, 2023
1 parent 6d04293 commit 8f0a2a0
Show file tree
Hide file tree
Showing 28 changed files with 990 additions and 148 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,24 @@ The SuiteScriptMocks object exported by default by this package has a number of
| currentScript | Details loaded when using runtime.getCurrentScript() |
| currentUser | Details loaded when using runtime.getCurrentUser() |
| currentSession | Details loaded when using runtime.getCurrentSession() |
| caches | Map of caches used by cache.getCache. |
| features | Map of which netsuite features are enabled, used by runtime.isFeatureInEffect |
| sentEmails | List of emails sent using N/email. |
| caches | List of caches used by cache.getCache. |
| files | List of files used by file.load, etc. Use File constructor when creating files to add to this. |
| createdFiles | List of files that have been created. |
| savedFiles | List of files that have been saved. |
| deletedFiles | List of files that have been deleted. |
| records | List of records used by record.load, etc. Use Record constructor when creating records to add to this. |
| savedRecords | List of records that have been saved. |
| createdRecords | List of records that have been created. |
| savedRecords | List of records that have been saved. |
| deletedRecords | List of records that have been deleted. |
| searches | List of searches used by search.load, etc. Use Search constructor when creating searches to add to this. |
| runSearches | List of searches that have been run. |
| searchResults | List of search results used to mock dynamically created and executed searches. Every search created with search.create will consume the first element in the list. |
| lookupFieldsResults | List of results used to mock search.lookupFields. Every call to search.lookupFields will consume the first element in the list. |
| taskStatuses | List of task statuses used by task.checkStatus. |
| submittedTasks | List of submitted tasks. |
| logs | List of logs. |
| logs | List of execution logs created by N/log |
| reset | Function used to reset the state of the mocks library. Advisable to do before every test run, likely in a beforeEach. |

For specific examples please look at the tests.
164 changes: 164 additions & 0 deletions __tests__/file/File.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import SuiteScriptMocks from "../..";
import Iterator from "../../lib/iterator.cjs";
import file from "../../lib/mocks/file/index.cjs";

let File;
let createdFile;
beforeEach(() => {
SuiteScriptMocks.reset();
File = new file.File({
id: 1,
folder: 1,
name: "test.csv",
fileType: file.Type.CSV,
contents: "this is a test",
});
createdFile = new file.File({
folder: 2,
name: "test.csv",
fileType: file.Type.CSV,
contents: "this is a test",
});
});
describe("file.File", () => {
describe("appendLine", () => {
it("should add line to contents", () => {
File.appendLine({ value: "another line" });
expect(File.contents).toBe("this is a test\nanother line");
});
});

describe("getContents", () => {
it("should return the saved file contents", () => {
expect(File.getContents()).toBe("this is a test");
});
it("should error if called directly after resetStream on created file", () => {
createdFile.resetStream();
expect(() => {
createdFile.getContents();
}).toThrow();
});
it("should return current contents when called for the first time on created file", () => {
expect(createdFile.getContents()).toBe("this is a test");
});
it("should always return same value when called on created file", () => {
expect(createdFile.getContents()).toBe("this is a test");
createdFile.resetStream();
createdFile.appendLine({ value: "another line" });
expect(createdFile.getContents()).toBe("this is a test");
});
});

describe("getReader", () => {
it("should return Reader object", () => {
expect(File.getReader()).toBeInstanceOf(file.Reader);
});
it("should return Reader of saved file contents", () => {
expect(File.getReader().contents).toBe("this is a test");
});
it("should return blank Reader if called before getContents on created file", () => {
expect(createdFile.getReader().contents).toBe("");
});
it("should return Reader for same value of getContents if called after getContents and before resetStream on created file", () => {
createdFile.getContents();
expect(createdFile.getReader().contents).toBe("this is a test");
});
it("should return Reader for same value of getContents if called after getContents and before resetStream on created file", () => {
createdFile.resetStream();
createdFile.appendLine({ value: "another line" });
createdFile.getContents();
expect(createdFile.getReader().contents).toBe("another line");
});
it("should return blank Reader if called after getContents and resetStream on created file", () => {
createdFile.getContents();
createdFile.resetStream();
expect(createdFile.getReader().contents).toBe("");
});
});

describe("getSegments", () => {
it("should throw if separator is not a string", () => {
expect(() => {
File.getSegments(4);
}).toThrow();
});
it("should return iterator of saved file contents split by separator", () => {
const iterator = File.getSegments(" ").iterator();
expect(iterator).toBeInstanceOf(Iterator);
expect(iterator.values).toEqual(["this", "is", "a", "test"]);
});
it("should return blank iterator if file wasn't loaded", () => {
const File = file.create({ name: "test.csv", fileType: file.Type.CSV, contents: "1 2 3" });
const iterator = File.getSegments(" ").iterator();
expect(iterator.next()).toEqual({ value: undefined, done: true });
});
});

describe("resetStream", () => {
it("should reset iterators", () => {
const iterator1 = File.lines.iterator();
const iterator2 = File.getSegments({ separator: " " }).iterator();
expect(iterator1.next()).toEqual({ value: "this is a test", done: false });
expect(iterator2.next()).toEqual({ value: "this", done: false });
File.resetStream();
expect(iterator1.next()).toEqual({ value: "this is a test", done: false });
expect(iterator2.next()).toEqual({ value: "this", done: false });
});
it("should reset readers", () => {
const reader = File.getReader();
expect(reader.readUntil("banana")).toBe("this is a test");
expect(reader.readUntil("banana")).toBe("");
File.resetStream();
expect(reader.readUntil("banana")).toBe("this is a test");
});
it("should blank out readers on created files", () => {
createdFile.getContents();
const reader = createdFile.getReader();
expect(reader.readUntil("banana")).toBe("this is a test");
expect(reader.readUntil("banana")).toBe("");
File.resetStream();
expect(reader.readUntil("banana")).toBe("");
});
});

describe("save", () => {
it("should error if called directly after resetStream on created file", () => {
createdFile.resetStream();
expect(() => {
createdFile.save();
}).toThrow();
});
it("should error if folder isn't set", () => {
delete createdFile.folder;
expect(() => {
createdFile.save();
}).toThrow();
});
it("should add created file to SuiteScriptMocks.createdFiles", () => {
createdFile.save();
expect(SuiteScriptMocks.createdFiles).toHaveLength(1);
expect(SuiteScriptMocks.savedFiles).toHaveLength(1);
});
it("should add file to SuiteScriptMocks.savedFiles", () => {
File.save();
expect(SuiteScriptMocks.savedFiles).toHaveLength(1);
});
it("should update existing file", () => {
File.contents = "update file";
File.save();
expect(SuiteScriptMocks.files[0].contents).toBe("update file");
});
it("should save copy of file", () => {
File.save();
expect(SuiteScriptMocks.files[0]).not.toBe(File);
});
it("should save without frozenContents and frozenContents2", () => {
File.frozenContents = "test";
File.frozenContents2 = "test";
File.save();
File = file.load(File.id);
expect(File.frozenContents).toBe(null);
expect(File.frozenContents2).toBe(null);
});
});
});
52 changes: 52 additions & 0 deletions __tests__/file/Reader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import file from "../../lib/mocks/file/index.cjs";

let reader;
beforeEach(() => {
reader = new file.Reader({
contents: "this is a test or something like that",
});
});

describe("file.Reader", () => {
describe("readChars", () => {
it("should return the next number of chars", () => {
expect(reader.readChars(5)).toBe("this ");
expect(reader.readChars(5)).toBe("is a ");
});
it("should stop at the end of the contents", () => {
reader.pointer = reader.contents.length - 2;
expect(reader.readChars(5)).toBe("at");
expect(reader.pointer).toBe(reader.contents.length);
});
it("should return blank if pointer is at end of the file", () => {
reader.pointer = reader.contents.length;
expect(reader.readChars(5)).toBe("");
expect(reader.pointer).toBe(reader.contents.length);
});
});

describe("readUntil", () => {
it("should return the next chars up until and including the supplied tag", () => {
expect(reader.readUntil(" ")).toBe("this ");
expect(reader.readUntil(" ")).toBe("is ");
expect(reader.readUntil("test")).toBe("a test");
});
it("should return the rest of the contents if the supplied tag is not found", () => {
expect(reader.readUntil("banana")).toBe(reader.contents);
expect(reader.pointer).toBe(reader.contents.length);
});
it("should return blank if pointer is at end of the file", () => {
reader.pointer = reader.contents.length;
expect(reader.readUntil("test")).toBe("");
expect(reader.pointer).toBe(reader.contents.length);
});
});

describe("reset", () => {
it("should set the pointer to 0", () => {
reader.pointer = 20;
reader.reset();
expect(reader.pointer).toBe(0);
});
});
});
137 changes: 137 additions & 0 deletions __tests__/file/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import SuiteScriptMocks from "../../index.cjs";
import file from "../../lib/mocks/file/index.cjs";

let File;
beforeEach(() => {
SuiteScriptMocks.reset();
File = new file.File({
id: 1,
name: "test.csv",
fileType: file.Type.CSV,
folder: 1,
});
SuiteScriptMocks.files = [File];
});
describe("file", () => {
describe("copy", () => {
it("should throw error if file does not exist", () => {
expect(() => {
file.copy({ folder: 2, id: 99999 });
}).toThrow();
});
it("should throw if conflictResolution is invalid", () => {
expect(() => {
file.copy({ folder: 2, id: 1, conflictResolution: "test" });
}).toThrow();
});
it("should not modify original file when modifying copy", () => {
const copy = file.copy({ folder: 2, id: 1 });
copy.name = "test2.csv";
expect(File.name).toBe("test.csv");
});
it("should throw if conflictResolution is FAIL and file with that name already exists in the folder", () => {
expect(() => {
file.copy({ folder: 1, id: 1 });
}).toThrow();
expect(() => {
file.copy({ folder: 1, id: 1, conflictResolution: file.NameConflictResolution.FAIL });
}).toThrow();
});
it("should overwrite file if conflictResolution is OVERWRITE and file with that name already exists in the folder", () => {
const copy = file.copy({ folder: 1, id: 1, conflictResolution: file.NameConflictResolution.OVERWRITE });
expect(copy.id).toBe(1);
expect(copy).not.toBe(File);
});
it("should overwrite file if conflictResolution is OVERWRITE_CONTENT_AND_ATTRIBUTES and file with that name already exists in the folder", () => {
const copy = file.copy({
folder: 1,
id: 1,
conflictResolution: file.NameConflictResolution.OVERWRITE_CONTENT_AND_ATTRIBUTES,
});
expect(copy.id).toBe(1);
expect(copy).not.toBe(File);
});
it("should rename file if conflictResolution is RENAME_TO_UNIQUE and file with that name already exists in the folder", () => {
const copy = file.copy({
folder: 1,
id: 1,
conflictResolution: file.NameConflictResolution.RENAME_TO_UNIQUE,
});
expect(copy.id).toBe(2);
expect(copy).not.toBe(File);
expect(copy.name).toBe("test(1).csv");

const copy2 = file.copy({
folder: 1,
id: 1,
conflictResolution: file.NameConflictResolution.RENAME_TO_UNIQUE,
});
expect(copy2.id).toBe(3);
expect(copy2).not.toBe(File);
expect(copy2.name).toBe("test(2).csv");
});
it("should return copy of file", () => {
const copy = file.copy({ folder: 2, id: 1 });
expect(copy.id).toBe(2);
expect(copy).not.toBe(File);
});
});

describe("create", () => {
it("should return new file", () => {
const rec = file.create({
name: "test.csv",
fileType: file.Type.CSV,
});
expect(rec).toBeInstanceOf(file.File);
expect(rec).toMatchObject({
id: null,
name: "test.csv",
fileType: file.Type.CSV,
});
});
});

describe("delete", () => {
it("should delete file if it exists", () => {
file.delete({ id: 1 });
expect(SuiteScriptMocks.files.length).toBe(0);
});
it("should return id of deleted file", () => {
expect(file.delete({ id: 1 })).toBe(1);
});
it("should throw error if file doesn't exist", () => {
expect(() => {
file.delete({ id: 99999 });
}).toThrow();
});
it("should add deleted file to SuiteScriptMocks.deletedFiles", () => {
file.delete({ id: 1 });
expect(SuiteScriptMocks.deletedFiles).toHaveLength(1);
expect(SuiteScriptMocks.deletedFiles[0].id).toBe(1);
});
});

describe("load", () => {
it("should return copy of file if it exists", () => {
const rec = file.load({ id: 1 });
expect(rec).not.toBe(File);
expect(rec.id).toBe(1);
});
it("should throw error if file doesn't exist", () => {
expect(() => {
file.load({ id: 99999 });
}).toThrow();
});
it("should not modify original file when modifying loaded file before save", () => {
const loadedfile = file.load({ id: 1 });
loadedfile.name = "test2.csv";
expect(File.name).toBe("test.csv");
});
it("should set savedContents on file to files contents", () => {
File.savedContents = "";
const loadedfile = file.load({ id: 1 });
expect(loadedfile.savedContents).toBe(loadedfile.contents);
});
});
});
Loading

0 comments on commit 8f0a2a0

Please sign in to comment.