Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0c5265b
feat: remove whitespaces
Magnus-Kuhn Feb 25, 2025
644a1b4
Merge remote-tracking branch 'origin/main' into whitespace-removal
Magnus-Kuhn Feb 25, 2025
cbcbae9
Merge branch 'main' into whitespace-removal
Magnus-Kuhn Feb 26, 2025
77a2f59
test: access right thing
Magnus-Kuhn Feb 26, 2025
64ffc22
fix: don't overwrite prototypes
Magnus-Kuhn Feb 26, 2025
2948248
Merge branch 'main' into whitespace-removal
Magnus-Kuhn Feb 26, 2025
68fc17f
refactor/fix: only trim JSON attribute values
Magnus-Kuhn Feb 27, 2025
c14c5eb
test: expect trimmed values
Magnus-Kuhn Feb 27, 2025
911132e
test: add trimming and duplicate check tests
Magnus-Kuhn Feb 27, 2025
62fade1
test: fix test
Magnus-Kuhn Feb 27, 2025
75a389b
Merge branch 'main' into whitespace-removal
Magnus-Kuhn Feb 27, 2025
495f38a
refactor/fix: remove whitespaces everywhere
Magnus-Kuhn Feb 28, 2025
82582ef
test: improve tests
Magnus-Kuhn Feb 28, 2025
22bffa2
test: fix/add tests
Magnus-Kuhn Feb 28, 2025
1397092
refactor: variable naming
Magnus-Kuhn Feb 28, 2025
319684d
Merge branch 'main' into whitespace-removal
mergify[bot] Feb 28, 2025
20440a1
Merge branch 'main' into whitespace-removal
mergify[bot] Mar 3, 2025
b1aaac9
test: remove unneeded checks
Magnus-Kuhn Mar 3, 2025
9d092ed
refactor: method ordering
Magnus-Kuhn Mar 3, 2025
b07c16f
test: remove more checks
Magnus-Kuhn Mar 3, 2025
cb8876a
test: add createAttributeRequestItem tests
Magnus-Kuhn Mar 3, 2025
3789bb8
Merge branch 'main' into whitespace-removal
mergify[bot] Mar 3, 2025
d72742d
Update packages/consumption/test/modules/requests/itemProcessors/crea…
Magnus-Kuhn Mar 4, 2025
41faf07
Merge branch 'main' into whitespace-removal
mergify[bot] Mar 5, 2025
e52cb66
Merge branch 'main' into whitespace-removal
Magnus-Kuhn Mar 6, 2025
e37cd7b
refactor: test helper signature
Magnus-Kuhn Mar 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ export class AttributesController extends ConsumptionBaseController {
}

const parsedParams = CreateRepositoryAttributeParams.from(params);
const trimmedAttribute = {
...parsedParams.content.toJSON(),
value: this.trimAttributeValue(parsedParams.content.value.toJSON() as AttributeValues.Identity.Json)
};
parsedParams.content = IdentityAttribute.from(trimmedAttribute);

let localAttribute = LocalAttribute.from({
id: parsedParams.id ?? (await ConsumptionIds.attribute.generate()),
createdAt: CoreDate.utc(),
Expand Down Expand Up @@ -405,6 +411,11 @@ export class AttributesController extends ConsumptionBaseController {
validate = true
): Promise<{ predecessor: LocalAttribute; successor: LocalAttribute }> {
const parsedSuccessorParams = AttributeSuccessorParams.from(successorParams);
const trimmedAttribute = {
...parsedSuccessorParams.content.toJSON(),
value: this.trimAttributeValue(parsedSuccessorParams.content.value.toJSON() as AttributeValues.Identity.Json)
};
parsedSuccessorParams.content = IdentityAttribute.from(trimmedAttribute);

if (validate) {
const validationResult = await this.validateRepositoryAttributeSuccession(predecessorId, parsedSuccessorParams);
Expand Down Expand Up @@ -1301,22 +1312,28 @@ export class AttributesController extends ConsumptionBaseController {
}

public async getRepositoryAttributeWithSameValue(value: AttributeValues.Identity.Json): Promise<LocalAttribute | undefined> {
const trimmedValue = this.trimAttributeValue(value);
const queryForRepositoryAttributeDuplicates = flattenObject({
content: {
"@type": "IdentityAttribute",
owner: this.identity.address.toString(),
value: value
value: trimmedValue
}
});
queryForRepositoryAttributeDuplicates["succeededBy"] = { $exists: false };
queryForRepositoryAttributeDuplicates["shareInfo"] = { $exists: false };

const matchingRepositoryAttributes = await this.getLocalAttributes(queryForRepositoryAttributeDuplicates);

const repositoryAttributeDuplicate = matchingRepositoryAttributes.find((duplicate) => _.isEqual(duplicate.content.value.toJSON(), value));
const repositoryAttributeDuplicate = matchingRepositoryAttributes.find((duplicate) => _.isEqual(duplicate.content.value.toJSON(), trimmedValue));
return repositoryAttributeDuplicate;
}

private trimAttributeValue(value: AttributeValues.Identity.Json): AttributeValues.Identity.Json {
const trimmedEntries = Object.entries(value).map((entry) => (typeof entry[1] === "string" ? [entry[0], entry[1].trim()] : entry));
return Object.fromEntries(trimmedEntries) as AttributeValues.Identity.Json;
}

public async getRelationshipAttributesOfValueTypeToPeerWithGivenKeyAndOwner(key: string, owner: CoreAddress, valueType: string, peer: CoreAddress): Promise<LocalAttribute[]> {
return await this.getLocalAttributes({
"content.@type": "RelationshipAttribute",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
BirthYear,
City,
Country,
DisplayName,
EMailAddress,
HouseNumber,
IdentityAttribute,
Expand Down Expand Up @@ -105,6 +106,21 @@ describe("AttributesController", function () {
mockEventBus.expectPublishedEvents(AttributeCreatedEvent);
});

test("should trim whitespace for a RepositoryAttribute", async function () {
const params: ICreateRepositoryAttributeParams = {
content: IdentityAttribute.from({
value: {
"@type": "DisplayName",
value: " aDisplayName\n"
},
owner: consumptionController.accountController.identity.address
})
};

const repositoryAttribute = await consumptionController.attributes.createRepositoryAttribute(params);
expect((repositoryAttribute.content.value as DisplayName).value).toBe("aDisplayName");
});

test("should create a new attribute of type SchematizedXML", async function () {
const params: ICreateRepositoryAttributeParams = {
content: IdentityAttribute.from({
Expand Down Expand Up @@ -163,6 +179,40 @@ describe("AttributesController", function () {
expect(attributesAfterCreate).toHaveLength(6);
});

test("should trim whitespace when creating a complex RepositoryAttribute and its children", async function () {
const identityAttribute = IdentityAttribute.from({
value: {
"@type": "StreetAddress",
recipient: "\taRecipient\r",
street: "\vaStreet\f",
houseNo: " aHouseNo\u00a0",
zipCode: " aZipCode\u2028",
city: " aCity ",
country: "DE"
},
validTo: CoreDate.utc(),
owner: consumptionController.accountController.identity.address
});

const address = await consumptionController.attributes.createRepositoryAttribute({
content: identityAttribute
});

expect((address.content.value as StreetAddress).recipient).toBe("aRecipient");
expect((address.content.value as StreetAddress).street.value).toBe("aStreet");
expect((address.content.value as StreetAddress).houseNo.value).toBe("aHouseNo");
expect((address.content.value as StreetAddress).zipCode.value).toBe("aZipCode");
expect((address.content.value as StreetAddress).city.value).toBe("aCity");

const childAttributes = await consumptionController.attributes.getLocalAttributes({
parentId: address.id.toString()
});
expect((childAttributes[0].content.value as Street).value).toBe("aStreet");
expect((childAttributes[1].content.value as HouseNumber).value).toBe("aHouseNo");
expect((childAttributes[2].content.value as ZipCode).value).toBe("aZipCode");
expect((childAttributes[3].content.value as City).value).toBe("aCity");
});

test("should trigger an AttributeCreatedEvent for each created child Attribute of a complex Attribute", async function () {
await consumptionController.attributes.getLocalAttributes();

Expand Down Expand Up @@ -1777,6 +1827,31 @@ describe("AttributesController", function () {
expect((successor.content.value.toJSON() as any).value).toBe("US");
});

test("should trim whitespace when succeeding a repository attribute", async function () {
const predecessor = await consumptionController.attributes.createRepositoryAttribute({
content: IdentityAttribute.from({
value: {
"@type": "GivenName",
value: " aGivenName "
},
owner: consumptionController.accountController.identity.address
})
});
const successorParams: IAttributeSuccessorParams = {
content: IdentityAttribute.from({
value: {
"@type": "GivenName",
value: " anotherGivenName "
},
owner: consumptionController.accountController.identity.address
})
};

const { successor } = await consumptionController.attributes.succeedRepositoryAttribute(predecessor.id, successorParams);
expect(successor).toBeDefined();
expect((successor.content.value.toJSON() as any).value).toBe("anotherGivenName");
});

test("should succeed a repository attribute updating tags but not the value", async function () {
const predecessor = await consumptionController.attributes.createRepositoryAttribute({
content: IdentityAttribute.from({
Expand Down Expand Up @@ -2031,6 +2106,45 @@ describe("AttributesController", function () {
}
});

test("should trim whitespace when succeeding a complex repository attribute", async function () {
const version1ChildValues = [" aNewStreet ", " aNewHouseNo ", " aNewZipCode ", " aNewCity ", "DE"];
const trimmedVersion1ChildValues = version1ChildValues.map((value) => value.trim());

const repoVersion1Params = {
content: IdentityAttribute.from({
value: {
"@type": "StreetAddress",
recipient: " aNewRecipient ",
street: version1ChildValues[0],
houseNo: version1ChildValues[1],
zipCode: version1ChildValues[2],
city: version1ChildValues[3],
country: version1ChildValues[4]
},
owner: consumptionController.accountController.identity.address
})
};

const { successor: repoVersion1 } = await consumptionController.attributes.succeedRepositoryAttribute(repoVersion0.id, repoVersion1Params);
expect((repoVersion1.content.value as StreetAddress).recipient).toBe("aNewRecipient");
expect((repoVersion1.content.value as StreetAddress).street.value).toBe("aNewStreet");
expect((repoVersion1.content.value as StreetAddress).houseNo.value).toBe("aNewHouseNo");
expect((repoVersion1.content.value as StreetAddress).zipCode.value).toBe("aNewZipCode");
expect((repoVersion1.content.value as StreetAddress).city.value).toBe("aNewCity");
expect((repoVersion1.content.value as StreetAddress).country.value).toBe("DE");

const repoVersion1ChildAttributes = await consumptionController.attributes.getLocalAttributes({
parentId: repoVersion1.id.toString()
});

const numberOfChildAttributes = version0ChildValues.length;
expect(repoVersion1ChildAttributes).toHaveLength(numberOfChildAttributes);

for (let i = 0; i < numberOfChildAttributes; i++) {
expect(repoVersion1ChildAttributes[i].content.value.toString()).toStrictEqual(trimmedVersion1ChildValues[i]);
}
});

test("should succeed a complex repository attribute adding an optional child", async function () {
repoVersion1Params = {
content: IdentityAttribute.from({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ export class ThenSteps {
return Promise.resolve();
}

public async aRepositoryAttributeIsCreated(): Promise<void> {
public async aRepositoryAttributeIsCreated(value?: AttributeValues.Identity.Json): Promise<void> {
expect((this.context.responseItemAfterAction as CreateAttributeAcceptResponseItem).attributeId).toBeDefined();

const createdSharedAttribute = await this.context.consumptionController.attributes.getLocalAttribute(
Expand All @@ -236,9 +236,10 @@ export class ThenSteps {

expect(createdRepositoryAttribute).toBeDefined();
expect(createdRepositoryAttribute!.shareInfo).toBeUndefined();
if (value) expect(createdRepositoryAttribute!.content.value.toJSON()).toStrictEqual(value);
}

public async anOwnSharedIdentityAttributeIsCreated(sourceAttribute?: CoreId): Promise<void> {
public async anOwnSharedIdentityAttributeIsCreated(params?: { sourceAttribute?: CoreId; value?: AttributeValues.Identity.Json }): Promise<void> {
expect((this.context.responseItemAfterAction as CreateAttributeAcceptResponseItem).attributeId).toBeDefined();

const createdAttribute = await this.context.consumptionController.attributes.getLocalAttribute(
Expand All @@ -249,9 +250,10 @@ export class ThenSteps {
expect(createdAttribute!.shareInfo).toBeDefined();
expect(createdAttribute!.shareInfo!.peer.toString()).toStrictEqual(this.context.peerAddress.toString());
expect(createdAttribute!.shareInfo!.sourceAttribute).toBeDefined();
if (params?.value) expect(createdAttribute!.content.value.toJSON()).toStrictEqual(params.value);

if (sourceAttribute) {
expect(createdAttribute!.shareInfo!.sourceAttribute!.toString()).toStrictEqual(sourceAttribute.toString());
if (params?.sourceAttribute) {
expect(createdAttribute!.shareInfo!.sourceAttribute!.toString()).toStrictEqual(params.sourceAttribute.toString());
}
}

Expand Down Expand Up @@ -305,6 +307,14 @@ export class ThenSteps {
expect((repositoryAttribute!.content as IdentityAttribute).tags?.sort()).toStrictEqual(tags.sort());
}

public async theSuccessorAttributeValueMatches(value: AttributeValues.Identity.Json): Promise<void> {
const attribute = await this.context.consumptionController.attributes.getLocalAttribute(
(this.context.responseItemAfterAction as AttributeSuccessionAcceptResponseItem).successorId
);

expect(attribute!.content.value.toJSON()).toStrictEqual(value);
}

public theCreatedAttributeHasTheAttributeIdFromTheResponseItem(): Promise<void> {
expect(this.context.createdAttributeAfterAction.id.toString()).toStrictEqual((this.context.givenResponseItem as CreateAttributeAcceptResponseItem).attributeId.toString());

Expand Down
Loading