diff --git a/packages/xml-locales/src/__snapshots__/xml-locales.test.ts.snap b/packages/xml-locales/src/__snapshots__/xml-locales.test.ts.snap
new file mode 100644
index 0000000..5816ae9
--- /dev/null
+++ b/packages/xml-locales/src/__snapshots__/xml-locales.test.ts.snap
@@ -0,0 +1,77 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`XmlLocales > XmlLocales constructor > constructor should parse xml data 1`] = `
+XmlJsonData {
+ "resources": {
+ "string": [
+ {
+ "#text": "value1",
+ "key_name": "key1",
+ },
+ ],
+ },
+}
+`;
+
+exports[`XmlLocales > XmlLocales constructor > should return json object 1`] = `
+XmlJsonData {
+ "resources": {
+ "#text": "
+
+
+",
+ "string": [
+ {
+ "#text": "value1",
+ "key_name": "key1",
+ },
+ {
+ "#text": "value2",
+ "key_name": "key2",
+ },
+ ],
+ },
+}
+`;
+
+exports[`XmlLocales > should return json object 1`] = `
+XmlJsonData {
+ "resources": {
+ "#text": "
+
+
+",
+ "string": [
+ {
+ "#text": "value1",
+ "key_name": "key1",
+ },
+ {
+ "#text": "value2",
+ "key_name": "key2",
+ },
+ ],
+ },
+}
+`;
+
+exports[`XmlLocales > should return xml string 1`] = `
+"
+ value1
+ value2
+"
+`;
+
+exports[`XmlLocales > to XML > should return xml string with formatting 1`] = `
+"
+ value1
+ value2
+"
+`;
+
+exports[`XmlLocales > to XML > should return xml string without formatting 1`] = `
+"value1value2
+
+
+"
+`;
diff --git a/packages/xml-locales/src/utils/__snapshots__/xml.test.ts.snap b/packages/xml-locales/src/utils/__snapshots__/xml.test.ts.snap
new file mode 100644
index 0000000..8cfb998
--- /dev/null
+++ b/packages/xml-locales/src/utils/__snapshots__/xml.test.ts.snap
@@ -0,0 +1,15 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`XmlParser > should format xml string 1`] = `
+"
+ value1
+ value2
+"
+`;
+
+exports[`XmlParser > should parse json to xml 1`] = `
+"value1value2
+
+
+"
+`;
diff --git a/packages/xml-locales/src/utils/helpers.test.ts b/packages/xml-locales/src/utils/helpers.test.ts
new file mode 100644
index 0000000..5540ccf
--- /dev/null
+++ b/packages/xml-locales/src/utils/helpers.test.ts
@@ -0,0 +1,49 @@
+import { describe, expect, test } from 'vitest';
+
+import {
+ checkKeyValueExist,
+ checkXmlKey,
+ replaceXmlNodeValue
+} from './helpers.js';
+
+const xmlData = {
+ resources: {
+ string: [
+ {
+ key_name: 'key1',
+ '#text': 'value1'
+ },
+ {
+ key_name: 'key2',
+ '#text': 'value2'
+ }
+ ]
+ }
+};
+
+describe('checkXmlKey', () => {
+ test('should return true if key exist', () => {
+ expect(checkXmlKey(xmlData, 'key1')).toBe(true);
+ });
+
+ test('should return false if key does not exist', () => {
+ expect(checkXmlKey(xmlData, 'key3')).toBe(false);
+ });
+});
+
+describe('checkKeyValueExist', () => {
+ test('should return true if key value exist', () => {
+ expect(checkKeyValueExist('value1', xmlData.resources.string)).toBe(true);
+ });
+
+ test('should return false if key value does not exist', () => {
+ expect(checkKeyValueExist('value3', xmlData.resources.string)).toBe(false);
+ });
+});
+
+describe('replaceXmlNodeValue', () => {
+ test('should replace the value of the key', () => {
+ const newXmlData = replaceXmlNodeValue(xmlData, 'key1', 'value3');
+ expect(newXmlData.resources.string[0]?.['#text']).toBe('value3');
+ });
+});
diff --git a/packages/xml-locales/src/utils/xml.test.ts b/packages/xml-locales/src/utils/xml.test.ts
new file mode 100644
index 0000000..e77e317
--- /dev/null
+++ b/packages/xml-locales/src/utils/xml.test.ts
@@ -0,0 +1,87 @@
+import { describe, expect, test } from 'vitest';
+
+import {
+ checkKeyValueExist,
+ checkXmlKey,
+ replaceXmlNodeValue
+} from './helpers.js';
+import { XmlJsonData, XmlParser } from './xml.js';
+
+const xmlData = `
+
+ value1
+ value2
+
+`;
+
+describe('XmlParser', () => {
+ test('should parse xml to json', () => {
+ const xmlParser = new XmlParser();
+ const jsonData = xmlParser.xmlToJson(xmlData);
+ expect(jsonData).toMatchObject({
+ resources: {
+ string: [
+ {
+ key_name: 'key1',
+ '#text': 'value1'
+ },
+ {
+ key_name: 'key2',
+ '#text': 'value2'
+ }
+ ]
+ }
+ });
+ });
+
+ test('should parse json to xml', () => {
+ const xmlParser = new XmlParser();
+ const jsonData = xmlParser.xmlToJson(xmlData);
+ const xmlString = xmlParser.jsonToXml(jsonData);
+ expect(xmlString).toMatchSnapshot();
+ });
+
+ test('should format xml string', () => {
+ const xmlParser = new XmlParser();
+ const jsonData = xmlParser.xmlToJson(xmlData);
+ const xmlString = xmlParser.jsonToXml(jsonData);
+ const formattedXmlString = xmlParser.formate(xmlString);
+ expect(formattedXmlString).toMatchSnapshot();
+ });
+});
+
+describe('XmlJsonData', () => {
+ test('should check if key exist', () => {
+ const xmlParser = new XmlParser();
+ const jsonData = xmlParser.xmlToJson(xmlData);
+ const xmlJsonData = new XmlJsonData(jsonData);
+
+ expect(checkXmlKey(xmlJsonData, 'key1')).toBe(true);
+ expect(checkXmlKey(xmlJsonData, 'key3')).toBe(false);
+ });
+
+ test('should check if key value exist', () => {
+ const xmlParser = new XmlParser();
+ const jsonData = xmlParser.xmlToJson(xmlData);
+ const xmlJsonData = new XmlJsonData(jsonData);
+ expect(checkKeyValueExist('value1', xmlJsonData.resources.string)).toBe(
+ true
+ );
+ expect(checkKeyValueExist('value3', xmlJsonData.resources.string)).toBe(
+ false
+ );
+ });
+
+ test('should replace the value of the key', () => {
+ const xmlParser = new XmlParser();
+ const jsonData = xmlParser.xmlToJson(xmlData);
+ const xmlJsonData = new XmlJsonData(jsonData);
+
+ expect(
+ checkKeyValueExist(
+ 'value3',
+ replaceXmlNodeValue(xmlJsonData, 'key1', 'value3').resources.string
+ )
+ ).toBe(true);
+ });
+});
diff --git a/packages/xml-locales/src/xml-locales.test.ts b/packages/xml-locales/src/xml-locales.test.ts
new file mode 100644
index 0000000..1ea7624
--- /dev/null
+++ b/packages/xml-locales/src/xml-locales.test.ts
@@ -0,0 +1,132 @@
+import { describe, expect, test } from 'vitest';
+
+import { XmlLocales } from './xml-locales.js';
+
+const xmlData = `
+ value1
+ value2
+`;
+
+const oneStringXmlData = `
+ value1
+`;
+
+describe('XmlLocales', () => {
+ describe('add', () => {
+ test('should add new node', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ const jsonXml = xmlLocales.add({ key: 'key3', value: 'value3' }).toJSON();
+ const newNode = jsonXml.resources.string[2];
+
+ expect(newNode?.key_name).toBe('key3');
+ expect(newNode?.['#text']).toBe('value3');
+ });
+
+ test('should replace the value of the key', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ const jsonXml = xmlLocales.add({ key: 'key1', value: 'value3' }).toJSON();
+ const newNode = jsonXml.resources.string[0];
+
+ expect(newNode?.key_name).toBe('key1');
+ expect(newNode?.['#text']).toBe('value3');
+ });
+ });
+
+ describe('remove', () => {
+ test('should remove a node of the key', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ xmlLocales.deleteByKey('key1');
+ const jsonXml = xmlLocales.toJSON();
+
+ expect(jsonXml.resources.string[0]?.['#text']).toBe('value2');
+ });
+
+ test('should remove a node of the value', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ xmlLocales.deleteByValue('value1');
+ const jsonXml = xmlLocales.toJSON();
+
+ expect(jsonXml.resources.string[0]?.['#text']).toBe('value2');
+ });
+
+ test('not found key or value', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ xmlLocales.deleteByKey('key3');
+ const jsonXml = xmlLocales.toJSON();
+
+ expect(jsonXml.resources.string[0]?.['#text']).toBe('value1');
+ });
+ });
+
+ describe('sort', () => {
+ test('should sorted by "asc"', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ xmlLocales.sort('asc');
+ const jsonXml = xmlLocales.toJSON();
+
+ expect(jsonXml.resources.string[0]?.key_name).toBe('key1');
+ });
+
+ test('should sorted by "desc"', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ xmlLocales.sort('desc');
+ const jsonXml = xmlLocales.toJSON();
+
+ expect(jsonXml.resources.string[1]?.key_name).toBe('key1');
+ });
+ });
+
+ describe('update', () => {
+ test('should update key', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ xmlLocales.update({ oldValue: 'key1', newValue: 'newKey1' });
+ const jsonXml = xmlLocales.toJSON();
+
+ expect(jsonXml.resources.string[0]?.key_name).toBe('newKey1');
+ });
+
+ test('should update value', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ xmlLocales.update({ oldValue: 'value1', newValue: 'newValue1' });
+ const jsonXml = xmlLocales.toJSON();
+
+ expect(jsonXml.resources.string[0]?.['#text']).toBe('newValue1');
+ });
+ });
+
+ describe('XmlLocales constructor', () => {
+ test('should throw error if xml data is not defined', () => {
+ expect(() => new XmlLocales()).toThrow('XML data is not defined');
+ });
+
+ test('constructor should parse xml data', () => {
+ const xmlLocales = new XmlLocales(oneStringXmlData);
+ const jsonXml = xmlLocales.toJSON();
+
+ expect(jsonXml).toMatchSnapshot();
+ });
+
+ test('should return json object', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ const jsonXml = xmlLocales.toJSON();
+
+ expect(jsonXml).toMatchSnapshot();
+ });
+ });
+
+ describe('to XML', () => {
+ test('should return xml string with formatting', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ const xmlString = xmlLocales.toXML();
+
+ expect(xmlString).toMatchSnapshot();
+ });
+
+ test('should return xml string without formatting', () => {
+ const xmlLocales = new XmlLocales(xmlData);
+ const xmlString = xmlLocales.toXML(false);
+
+ expect(xmlString).toMatchSnapshot();
+ });
+ });
+});