From b51b17194ea1780d774b39a0439e329dbd7dedd8 Mon Sep 17 00:00:00 2001 From: brianvoe Date: Wed, 29 Nov 2023 16:47:32 -0600 Subject: [PATCH 1/9] readme - update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2520a8a4..5560c46a 100644 --- a/README.md +++ b/README.md @@ -852,7 +852,7 @@ ErrorRuntime() error ### School ```go -school() string +School() string ``` ## Template From 74c67cabb15ed31eb1767875ddad00fd58e5ad4c Mon Sep 17 00:00:00 2001 From: brianvoe Date: Fri, 1 Dec 2023 13:32:10 -0600 Subject: [PATCH 2/9] fields - minor arrangement --- csv.go | 14 +++++++------- json.go | 16 ++++++++-------- xml.go | 16 ++++++++-------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/csv.go b/csv.go index b050e453..1a780ff6 100644 --- a/csv.go +++ b/csv.go @@ -138,13 +138,19 @@ func addFileCSVLookup() { Output: "[]byte", ContentType: "text/csv", Params: []Param{ + {Field: "delimiter", Display: "Delimiter", Type: "string", Default: ",", Description: "Separator in between row values"}, {Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows"}, {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function"}, - {Field: "delimiter", Display: "Delimiter", Type: "string", Default: ",", Description: "Separator in between row values"}, }, Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { co := CSVOptions{} + delimiter, err := info.GetString(m, "delimiter") + if err != nil { + return nil, err + } + co.Delimiter = delimiter + rowcount, err := info.GetInt(m, "rowcount") if err != nil { return nil, err @@ -169,12 +175,6 @@ func addFileCSVLookup() { } } - delimiter, err := info.GetString(m, "delimiter") - if err != nil { - return nil, err - } - co.Delimiter = delimiter - f := &Faker{Rand: r} csvOut, err := csvFunc(f, &co) if err != nil { diff --git a/json.go b/json.go index 4c3e6806..95a9b372 100644 --- a/json.go +++ b/json.go @@ -14,8 +14,8 @@ import ( type JSONOptions struct { Type string `json:"type" xml:"type" fake:"{randomstring:[array,object]}"` // array or object RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` - Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` Indent bool `json:"indent" xml:"indent"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` } type jsonKeyVal struct { @@ -205,8 +205,8 @@ func addFileJSONLookup() { Params: []Param{ {Field: "type", Display: "Type", Type: "string", Default: "object", Options: []string{"object", "array"}, Description: "Type of JSON, object or array"}, {Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows in JSON array"}, - {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, {Field: "indent", Display: "Indent", Type: "bool", Default: "false", Description: "Whether or not to add indents and newlines"}, + {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, }, Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { jo := JSONOptions{} @@ -223,6 +223,12 @@ func addFileJSONLookup() { } jo.RowCount = rowcount + indent, err := info.GetBool(m, "indent") + if err != nil { + return nil, err + } + jo.Indent = indent + fieldsStr, err := info.GetStringArray(m, "fields") if err != nil { return nil, err @@ -241,12 +247,6 @@ func addFileJSONLookup() { } } - indent, err := info.GetBool(m, "indent") - if err != nil { - return nil, err - } - jo.Indent = indent - f := &Faker{Rand: r} return jsonFunc(f, &jo) }, diff --git a/xml.go b/xml.go index e851fb86..097ae6c4 100644 --- a/xml.go +++ b/xml.go @@ -15,8 +15,8 @@ type XMLOptions struct { RootElement string `json:"root_element" xml:"root_element"` RecordElement string `json:"record_element" xml:"record_element"` RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` - Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` Indent bool `json:"indent" xml:"indent"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` } type xmlArray struct { @@ -292,8 +292,8 @@ func addFileXMLLookup() { {Field: "rootelement", Display: "Root Element", Type: "string", Default: "xml", Description: "Root element wrapper name"}, {Field: "recordelement", Display: "Record Element", Type: "string", Default: "record", Description: "Record element for each record row"}, {Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows in JSON array"}, - {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, {Field: "indent", Display: "Indent", Type: "bool", Default: "false", Description: "Whether or not to add indents and newlines"}, + {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, }, Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { xo := XMLOptions{} @@ -327,6 +327,12 @@ func addFileXMLLookup() { return nil, err } + indent, err := info.GetBool(m, "indent") + if err != nil { + return nil, err + } + xo.Indent = indent + // Check to make sure fields has length if len(fieldsStr) > 0 { xo.Fields = make([]Field, len(fieldsStr)) @@ -340,12 +346,6 @@ func addFileXMLLookup() { } } - indent, err := info.GetBool(m, "indent") - if err != nil { - return nil, err - } - xo.Indent = indent - f := &Faker{Rand: r} return xmlFunc(f, &xo) }, From bf47167374e3d8abeef6062d3a06721a2954e0db Mon Sep 17 00:00:00 2001 From: brianvoe Date: Sun, 3 Dec 2023 06:32:08 -0600 Subject: [PATCH 3/9] readme - minor fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5560c46a..53ebbc7e 100644 --- a/README.md +++ b/README.md @@ -185,14 +185,14 @@ For example, this is useful when it is not possible to modify the struct that yo // or just return a static value type CustomString string -func (c *CustomString) Fake(faker *gofakeit.Faker) any { +func (c *CustomString) Fake(faker *gofakeit.Faker) (any, error) { return CustomString("my custom string") } // Imagine a CustomTime type that is needed to support a custom JSON Marshaler type CustomTime time.Time -func (c *CustomTime) Fake(faker *gofakeit.Faker) any { +func (c *CustomTime) Fake(faker *gofakeit.Faker) (any, error) { return CustomTime(time.Now()) } From bcfe33436ff6fea2191b2d300933974427ce34ca Mon Sep 17 00:00:00 2001 From: brianvoe Date: Tue, 5 Dec 2023 14:47:57 -0600 Subject: [PATCH 4/9] any - updated to use any --- address.go | 2 +- car.go | 2 +- helpers_test.go | 2 +- lookup.go | 8 ++++---- payment.go | 2 +- person.go | 2 +- struct_test.go | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/address.go b/address.go index 2923b17b..e097c66a 100644 --- a/address.go +++ b/address.go @@ -209,7 +209,7 @@ func addAddressLookup() { latitude: "23.058758", longitude: "89.022594" }`, - Output: "map[string]interface", + Output: "map[string]any", ContentType: "application/json", Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return address(r), nil diff --git a/car.go b/car.go index 90685bda..ec2b9118 100644 --- a/car.go +++ b/car.go @@ -76,7 +76,7 @@ func addCarLookup() { Display: "Car", Category: "car", Description: "Random car set of data", - Output: "map[string]interface", + Output: "map[string]any", ContentType: "application/json", Example: `{type: "Passenger car mini", fuel: "Gasoline", transmission: "Automatic", brand: "Fiat", model: "Freestyle Fwd", year: "1972"}`, Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { diff --git a/helpers_test.go b/helpers_test.go index 885a3edd..b5bb9f65 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -263,7 +263,7 @@ func TestAnyToStringEdgeCases(t *testing.T) { // Test with a struct containing a nil interface field type nilInterfaceFieldStruct struct { - Data interface{} + Data any } nilInterfaceStruct := nilInterfaceFieldStruct{} want = `{"Data":null}` diff --git a/lookup.go b/lookup.go index 58698ba8..312d5db8 100644 --- a/lookup.go +++ b/lookup.go @@ -293,17 +293,17 @@ func (i *Info) GetAny(m *MapParams, field string) (any, error) { //return anyValue, nil } -// GetMap will retrieve map[string]interface{} field from data -func (i *Info) GetMap(m *MapParams, field string) (map[string]interface{}, error) { +// GetMap will retrieve map[string]any field from data +func (i *Info) GetMap(m *MapParams, field string) (map[string]any, error) { _, value, err := i.GetField(m, field) if err != nil { return nil, err } - var mapValue map[string]interface{} + var mapValue map[string]any err = json.Unmarshal([]byte(value[0]), &mapValue) if err != nil { - return nil, fmt.Errorf("%s field could not parse to map[string]interface{}", field) + return nil, fmt.Errorf("%s field could not parse to map[string]any", field) } return mapValue, nil diff --git a/payment.go b/payment.go index ead89c14..fb18e4a3 100644 --- a/payment.go +++ b/payment.go @@ -304,7 +304,7 @@ func addPaymentLookup() { Category: "payment", Description: "Random credit card data set", Example: `{type: "Visa", number: "4136459948995369", exp: "01/21", cvv: "513"}`, - Output: "map[string]interface", + Output: "map[string]any", Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return creditCard(r), nil }, diff --git a/person.go b/person.go index da835a0b..1f56e6ce 100644 --- a/person.go +++ b/person.go @@ -244,7 +244,7 @@ func addPersonLookup() { cvv: "353" } }`, - Output: "map[string]interface", + Output: "map[string]any", ContentType: "application/json", Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return person(r), nil diff --git a/struct_test.go b/struct_test.go index c0e021a3..d95fb220 100644 --- a/struct_test.go +++ b/struct_test.go @@ -895,7 +895,7 @@ func TestStructArrayWithInvalidCustomFunc(t *testing.T) { func TestStructMapWithCustomFunction(t *testing.T) { AddFuncLookup("custom_map", Info{ - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return map[string]string{"abc": "123"}, nil }, }) From 0579cd339c8d64744a0b87a5c5c34961f4807bdb Mon Sep 17 00:00:00 2001 From: brianvoe Date: Tue, 5 Dec 2023 14:51:35 -0600 Subject: [PATCH 5/9] school - updated benchmark name --- number.go | 4 ++-- school_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/number.go b/number.go index 345df523..43f7fd99 100644 --- a/number.go +++ b/number.go @@ -515,7 +515,7 @@ func addNumberLookup() { Params: []Param{ {Field: "ints", Display: "Integers", Type: "[]int", Description: "Delimited separated integers"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { ints, err := info.GetIntArray(m, "ints") if err != nil { return nil, err @@ -534,7 +534,7 @@ func addNumberLookup() { Params: []Param{ {Field: "uints", Display: "Unsigned Integers", Type: "[]uint", Description: "Delimited separated unsigned integers"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { uints, err := info.GetUintArray(m, "uints") if err != nil { return nil, err diff --git a/school_test.go b/school_test.go index e6ac3001..63531e27 100644 --- a/school_test.go +++ b/school_test.go @@ -19,7 +19,7 @@ func ExampleFaker_School() { // Harborview State Academy } -func BenchmarkExampleFaker_SchoolGen(b *testing.B) { +func BenchmarkSchool(b *testing.B) { b.Run("package", func(b *testing.B) { for i := 0; i < b.N; i++ { School() @@ -41,4 +41,4 @@ func BenchmarkExampleFaker_SchoolGen(b *testing.B) { f.School() } }) -} \ No newline at end of file +} From c9ce0bbc67d68f66be85f48ba40daa0baa56666d Mon Sep 17 00:00:00 2001 From: brianvoe Date: Tue, 5 Dec 2023 16:52:44 -0600 Subject: [PATCH 6/9] template - removed unused params --- template.go | 22 ++-------------------- template_test.go | 8 ++++---- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/template.go b/template.go index 2eb02cb4..415c0af7 100644 --- a/template.go +++ b/template.go @@ -38,7 +38,6 @@ func (f *Faker) Template(template string, co *TemplateOptions) (string, error) { // MarkdownOptions defines values needed for markdown document generation type MarkdownOptions struct { - SectionsCount int `json:"sections" xml:"sections" fake:"{number:1,10}"` } // Template for Markdown @@ -109,7 +108,6 @@ func (f *Faker) Markdown(co *MarkdownOptions) (string, error) { // EmailOptions defines values needed for email document generation type EmailOptions struct { - SectionsCount int `json:"sections" xml:"sections" fake:"{number:1,10}"` } // Template for email text @@ -349,16 +347,8 @@ func addTemplateLookup() { Description: "Generates random markdown document", Example: "", Output: "string", - Params: []Param{ - {Field: "sections_count", Display: "Body Sections", Type: "int", Default: "1", Optional: true, Description: "Number of content sections to generate"}, - }, Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { - sections, err := info.GetInt(m, "sections_count") - if err != nil { - sections = 1 - } - - template_result, err := templateFunc(templateMarkdown, templateFuncMap(r, nil), &MarkdownOptions{SectionsCount: sections}) + template_result, err := templateFunc(templateMarkdown, templateFuncMap(r, nil), &MarkdownOptions{}) return string(template_result), err }, }) @@ -369,16 +359,8 @@ func addTemplateLookup() { Description: "Generates random email document.", Example: "", Output: "string", - Params: []Param{ - {Field: "sections_count", Display: "Body Sections", Type: "int", Default: "1", Optional: true, Description: "Number of content sections to generate"}, - }, Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { - sections, err := info.GetInt(m, "sections_count") - if err != nil { - sections = 1 - } - - template_result, err := templateFunc(templateEmail, templateFuncMap(r, nil), &EmailOptions{SectionsCount: sections}) + template_result, err := templateFunc(templateEmail, templateFuncMap(r, nil), &EmailOptions{}) return string(template_result), err }, }) diff --git a/template_test.go b/template_test.go index 707bdb91..dafc876f 100644 --- a/template_test.go +++ b/template_test.go @@ -156,7 +156,7 @@ func TestTemplateNoOptions(t *testing.T) { func ExampleEmailText() { Seed(11) - value, err := EmailText(&EmailOptions{SectionsCount: 3}) + value, err := EmailText(&EmailOptions{}) if err != nil { fmt.Println(err) } @@ -193,7 +193,7 @@ func ExampleEmailText() { func ExampleFaker_EmailText() { f := New(11) - value, err := f.EmailText(&EmailOptions{SectionsCount: 3}) + value, err := f.EmailText(&EmailOptions{}) if err != nil { fmt.Println(err) } @@ -231,7 +231,7 @@ func ExampleFaker_EmailText() { func ExampleMarkdown() { Seed(11) - value, err := Markdown(&MarkdownOptions{SectionsCount: 3}) + value, err := Markdown(&MarkdownOptions{}) if err != nil { fmt.Println(err) } @@ -270,7 +270,7 @@ func ExampleMarkdown() { func ExampleFaker_Markdown() { f := New(11) - value, err := f.Markdown(&MarkdownOptions{SectionsCount: 2}) + value, err := f.Markdown(&MarkdownOptions{}) if err != nil { fmt.Println(err) } From 4f7de6eb26925ae23609667625545a6692f5f5a6 Mon Sep 17 00:00:00 2001 From: brianvoe Date: Tue, 5 Dec 2023 16:52:56 -0600 Subject: [PATCH 7/9] readme - updated --- README.md | 86 +++++++++++++++++++++++-------------------------------- 1 file changed, 36 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 53ebbc7e..3f2c6b93 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![alt text](https://raw.githubusercontent.com/brianvoe/gofakeit/master/logo.png) -# Gofakeit [![Go Report Card](https://goreportcard.com/badge/github.com/brianvoe/gofakeit)](https://goreportcard.com/report/github.com/brianvoe/gofakeit) ![Test](https://github.com/brianvoe/gofakeit/workflows/Test/badge.svg?branch=master) [![codecov.io](https://codecov.io/github/brianvoe/gofakeit/branch/master/graph/badge.svg)](https://codecov.io/github/brianvoe/gofakeit) [![GoDoc](https://godoc.org/github.com/brianvoe/gofakeit/v6?status.svg)](https://godoc.org/github.com/brianvoe/gofakeit/v6) [![license](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/brianvoe/gofakeit/master/LICENSE.txt) +# Gofakeit [![Go Report Card](https://goreportcard.com/badge/github.com/brianvoe/gofakeit)](https://goreportcard.com/report/github.com/brianvoe/gofakeit) ![Test](https://github.com/brianvoe/gofakeit/workflows/Test/badge.svg?branch=master) [![GoDoc](https://godoc.org/github.com/brianvoe/gofakeit/v6?status.svg)](https://godoc.org/github.com/brianvoe/gofakeit/v6) [![license](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/brianvoe/gofakeit/master/LICENSE.txt) Random data generator written in go @@ -10,7 +10,7 @@ Random data generator written in go ## Features -- [260+ Functions!!!](#functions) +- [310+ Functions!!!](#functions) - [Random Sources](#random-sources) - [Global Rand](#global-rand-set) - [Struct Generator](#struct) @@ -24,7 +24,7 @@ Random data generator written in go ## Contributors -Thanks to everyone who has contributed to Gofakeit! +Thank you to all our Gofakeit contributors! @@ -266,8 +266,6 @@ fmt.Printf("%s", f.FriendName) // bill fmt.Printf("%s", f.JumbleWord) // loredlowlh ``` - - ## Templates Generate custom outputs using golang's template engine [https://pkg.go.dev/text/template](https://pkg.go.dev/text/template). @@ -280,7 +278,7 @@ Additional Available Functions - ToLower(s string) string // Make string lower case - ToString(s any) // Convert to string - ToDate(s string) time.Time // Convert string to date -- SpliceAny(args ...any) []any // Build a slice of interfaces, used with Weighted +- SpliceAny(args ...any) []any // Build a slice of anys, used with Weighted - SpliceString(args ...string) []string // Build a slice of strings, used with Teams and RandomString - SpliceUInt(args ...uint) []uint // Build a slice of uint, used with Dice and RandomUint - SpliceInt(args ...int) []int // Build a slice of int, used with RandomInt @@ -365,6 +363,28 @@ FileExtension() string FileMimeType() string ``` +### Template + +Passing `nil` will auto generate data using a random set of generators. + +```go +Template(co *TemplateOptions) (string, error) +Markdown(co *MarkdownOptions) (string, error) +EmailText(co *EmailOptions) (string, error) +FixedWidth(co *FixedWidthOptions) (string, error) +``` + +### Product + +```go +Product() *ProductInfo +ProductName() string +ProductDescription() string +ProductCategory() string +ProductFeature() string +ProductMaterial() string + +``` ### Person @@ -457,9 +477,8 @@ CarTransmissionType() string ### Words -#### Noun - ```go +// Nouns Noun() string NounCommon() string NounConcrete() string @@ -469,20 +488,14 @@ NounCollectiveAnimal() string NounCollectiveThing() string NounCountable() string NounUncountable() string -``` -#### Verb - -```go +// Verbs Verb() string VerbAction() string VerbLinking() string VerbHelping() string -``` - -#### Adverb -```go +// Adverbs Adverb() string AdverbManner() string AdverbDegree() string @@ -491,20 +504,14 @@ AdverbTimeDefinite() string AdverbTimeIndefinite() string AdverbFrequencyDefinite() string AdverbFrequencyIndefinite() string -``` - -#### Proposition -```go +// Propositions Preposition() string PrepositionSimple() string PrepositionDouble() string PrepositionCompound() string -``` - -#### Adjective -```go +// Adjectives Adjective() string AdjectiveDescriptive() string AdjectiveQuantitative() string @@ -513,11 +520,8 @@ AdjectiveDemonstrative() string AdjectivePossessive() string AdjectiveInterrogative() string AdjectiveIndefinite() string -``` -#### Pronoun - -```go +// Pronouns Pronoun() string PronounPersonal() string PronounObject() string @@ -526,11 +530,8 @@ PronounReflective() string PronounDemonstrative() string PronounInterrogative() string PronounRelative() string -``` -#### Connective - -```go +// Connectives Connective() string ConnectiveTime() string ConnectiveComparative() string @@ -538,17 +539,11 @@ ConnectiveComplaint() string ConnectiveListing() string ConnectiveCasual() string ConnectiveExamplify() string -``` - -#### Word -```go +// Words Word() string -``` - -#### Sentences -```go +// Sentences Sentence(wordCount int) string Paragraph(paragraphCount int, sentenceCount int, wordCount int, separator string) string LoremIpsumWord() string @@ -576,7 +571,7 @@ Dessert() string ```go Bool() bool UUID() string -Weighted(options []any, weights []float32) +Weighted(options []any, weights []float32) (any, error) FlipACoin() string RandomMapKey(mapI any) any ShuffleAnySlice(v any) @@ -854,12 +849,3 @@ ErrorRuntime() error ```go School() string ``` - -## Template - -```go -Template(co *TemplateOptions) (string, error) // Generates custom documents -Markdown(co *MarkdownOptions) (string, error) // Generates markdown documents -EmailText(co *EmailOptions) (string, error) // Generates email documents -FixedWidth(co *FixedWidthOptions) (string, error) // Generates fixed width documents -``` \ No newline at end of file From 19cf99c3da6979eb530ff9d5154e99f907d5b6ae Mon Sep 17 00:00:00 2001 From: brianvoe Date: Tue, 5 Dec 2023 16:54:03 -0600 Subject: [PATCH 8/9] products - added various functions for product use --- data/data.go | 1 + data/product.go | 64 +++++++++++++ lookup.go | 1 + product.go | 248 ++++++++++++++++++++++++++++++++++++++++++++++++ product_test.go | 231 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 545 insertions(+) create mode 100644 data/product.go create mode 100644 product.go create mode 100644 product_test.go diff --git a/data/data.go b/data/data.go index b293b5ad..51a4f496 100644 --- a/data/data.go +++ b/data/data.go @@ -31,6 +31,7 @@ var Data = map[string]map[string][]string{ "book": Books, "movie": Movies, "school": School, + "product": Product, } func List() map[string][]string { diff --git a/data/product.go b/data/product.go new file mode 100644 index 00000000..127d6655 --- /dev/null +++ b/data/product.go @@ -0,0 +1,64 @@ +package data + +var Product = map[string][]string{ + "category": { + "electronics", "clothing", "home appliances", "furniture", + "automotive parts", "beauty and personal care", "books", "sports equipment", + "toys and games", "outdoor gear", "pet supplies", "kitchenware", + "health and wellness", "tools and hardware", "office supplies", + "baby products", "jewelry", "home decor", "musical instruments", + "fitness equipment", "mobile phones", "computer accessories", "cameras and photography", + "gardening supplies", "bedding and linens", "food and groceries", "party supplies", + "craft and diy supplies", "camping gear", "watches", "luggage and travel accessories", + "board games", "art supplies", "stationery", "bath and shower products", + "sunglasses", "educational toys", "headphones and earbuds", "sneakers and athletic shoes", + "coffee and tea products", "bicycles and accessories", "cookware", "cosmetics", + "home improvement", "pet food", "laptop bags and cases", "home security systems", + "musical accessories", "skincare products", "smart home devices", + }, + + "adjective": { + "bold", "swift", "pure", "smart", "fresh", + "cool", "sharp", "zen", "bright", "quick", + "robust", "sleek", "versatile", "innovative", "compact", + "luxe", "modular", "precision", "stream", + }, + + "name": { + "phone", "laptop", "tablet", "watch", "camera", + "headphones", "speaker", "drone", "car", "bike", + "appliance", "gadget", "tool", "toy", "game", + "computer", "console", "smartwatch", "fitness tracker", "smart home device", + "robot", "router", "television", "smart speaker", "vr headset", + "earbuds", "printer", "mouse", "keyboard", "monitor", + "microwave", "blender", "vacuum", "fan", "toaster", + "clock", "lamp", "shaver", "scale", "thermometer", + "fridge", "oven", "mixer", "iron", "hair dryer", + "fan", "scale", "thermostat", "router", "lightbulb", + }, + + "feature": { + "wireless", "smart", "eco-friendly", "advanced", "compact", + "high-performance", "energy-efficient", "portable", "durable", "stylish", + "touchscreen", "water-resistant", "noise-canceling", "voice-controlled", "ultra-lightweight", + "multi-functional", "user-friendly", "fast-charging", "biometric", "gps-enabled", + }, + + "material": { + "titanium", "carbon", "alloy", "bamboo", "leather", + "glass", "ceramic", "aluminum", "stainless", "wood", + "plastic", "rubber", "silicon", "fabric", "paper", + "gold", "silver", "brass", "copper", "bronze", + "chrome", "marble", "granite", "porcelain", "plexiglass", + "quartz", "felt", "suede", + }, + + "suffix": { + "tech", "pro", "x", "plus", "elite", + "spark", "nexus", "nova", "fusion", "sync", + "edge", "boost", "max", "link", "prime", + "zoom", "pulse", "dash", "connect", "blaze", + "quantum", "spark", "vertex", "core", "flux", + "turbo", "shift", "wave", "matrix", + }, +} diff --git a/lookup.go b/lookup.go index 312d5db8..0a164786 100644 --- a/lookup.go +++ b/lookup.go @@ -89,6 +89,7 @@ func initLookup() { addNumberLookup() addPaymentLookup() addPersonLookup() + addProductLookup() addSchoolLookup() addStringLookup() addTemplateLookup() diff --git a/product.go b/product.go new file mode 100644 index 00000000..cecb7a8f --- /dev/null +++ b/product.go @@ -0,0 +1,248 @@ +package gofakeit + +import ( + "fmt" + "math/rand" + "strings" +) + +type ProductInfo struct { + Name string `json:"name" xml:"name"` + Description string `json:"description" xml:"description"` + Categories []string `json:"categories" xml:"categories"` + Price float64 `json:"price" xml:"price"` + Features []string `json:"features" xml:"features"` + Color string `json:"color" xml:"color"` + Material string `json:"material" xml:"material"` + UPC string `json:"upc" xml:"upc"` +} + +// Product will generate a random set of product information +func Product() *ProductInfo { return product(globalFaker.Rand) } + +// Product will generate a random set of product information +func (f *Faker) Product() *ProductInfo { return product(f.Rand) } + +func product(r *rand.Rand) *ProductInfo { + // Categories + categories := []string{} + weightedCategory, _ := weighted(r, []any{1, 2, 3, 4}, []float32{1, 4, 3, 4}) + + for i := 0; i < weightedCategory.(int); i++ { + categories = append(categories, productCategory(r)) + } + + // Features + features := []string{} + for i := 0; i < number(r, 1, 5); i++ { + features = append(features, productFeature(r)) + } + + product := &ProductInfo{ + Name: productName(r), + Description: productDescription(r), + Categories: categories, + Price: price(r, 3.00, 100.00), + UPC: productUPC(r), + Features: features, + Color: safeColor(r), + Material: productMaterial(r), + } + + return product +} + +// ProductName will generate a random product name +func ProductName() string { return productName(globalFaker.Rand) } + +// ProductName will generate a random product name +func (f *Faker) ProductName() string { return productName(f.Rand) } + +func productName(r *rand.Rand) string { + name := getRandValue(r, []string{"product", "name"}) + switch number(r, 0, 9) { + case 1: + // Name + Adjective + Feature + return fmt.Sprintf("%s %s %s", name, getRandValue(r, []string{"product", "adjective"}), productFeature(r)) + case 2: + // Adjective + Material + Name + return fmt.Sprintf("%s %s %s", getRandValue(r, []string{"product", "adjective"}), productMaterial(r), name) + case 3: + // Color + Name + Suffix + return fmt.Sprintf("%s %s %s", safeColor(r), name, getRandValue(r, []string{"product", "suffix"})) + case 4: + // Feature + Name + Adjective + return fmt.Sprintf("%s %s %s", productFeature(r), name, getRandValue(r, []string{"product", "adjective"})) + case 5: + // Material + Color + Name + return fmt.Sprintf("%s %s %s", productMaterial(r), safeColor(r), name) + case 6: + // Name + Suffix + Material + return fmt.Sprintf("%s %s %s", name, getRandValue(r, []string{"product", "suffix"}), productMaterial(r)) + case 7: + // Adjective + Feature + Name + return fmt.Sprintf("%s %s %s", getRandValue(r, []string{"product", "adjective"}), productFeature(r), name) + case 8: + // Color + Material + Name + return fmt.Sprintf("%s %s %s", safeColor(r), productMaterial(r), name) + case 9: + // Suffix + Adjective + Name + return fmt.Sprintf("%s %s %s", getRandValue(r, []string{"product", "suffix"}), getRandValue(r, []string{"product", "adjective"}), name) + } + + // case: 0 - Adjective + Name + Suffix + return fmt.Sprintf("%s %s %s", getRandValue(r, []string{"product", "adjective"}), name, getRandValue(r, []string{"product", "suffix"})) +} + +// ProductDescription will generate a random product description +func ProductDescription() string { return productDescription(globalFaker.Rand) } + +// ProductDescription will generate a random product description +func (f *Faker) ProductDescription() string { return productDescription(f.Rand) } + +func productDescription(r *rand.Rand) string { + desc := []string{} + for i := 0; i < number(r, 1, 3); i++ { + desc = append(desc, sentence(r, number(r, 5, 15))) + } + + return strings.Join(desc, " ") +} + +// ProductCategory will generate a random product category +func ProductCategory() string { return productCategory(globalFaker.Rand) } + +// ProductCategory will generate a random product category +func (f *Faker) ProductCategory() string { return productCategory(f.Rand) } + +func productCategory(r *rand.Rand) string { + return getRandValue(r, []string{"product", "category"}) +} + +// ProductFeature will generate a random product feature +func ProductFeature() string { return productFeature(globalFaker.Rand) } + +// ProductFeature will generate a random product feature +func (f *Faker) ProductFeature() string { return productFeature(f.Rand) } + +func productFeature(r *rand.Rand) string { + return getRandValue(r, []string{"product", "feature"}) +} + +// ProductMaterial will generate a random product material +func ProductMaterial() string { return productMaterial(globalFaker.Rand) } + +// ProductMaterial will generate a random product material +func (f *Faker) ProductMaterial() string { return productMaterial(f.Rand) } + +func productMaterial(r *rand.Rand) string { + return getRandValue(r, []string{"product", "material"}) +} + +// ProductUPC will generate a random product UPC +func ProductUPC() string { return productUPC(globalFaker.Rand) } + +// ProductUPC will generate a random product UPC +func (f *Faker) ProductUPC() string { return productUPC(f.Rand) } + +func productUPC(r *rand.Rand) string { + // The first digit of a UPC is a fixed digit (usually 0) + upc := "0" + + // Generate the remaining 11 digits randomly + for i := 1; i < 12; i++ { + digit := number(r, 0, 9) + upc += fmt.Sprintf("%d", digit) + } + + return upc +} + +func addProductLookup() { + AddFuncLookup("product", Info{ + Display: "Product Info", + Category: "product", + Description: "Random project info", + Output: "map[string]any", + ContentType: "application/json", + Example: `{ + "name": "olive copper monitor", + "description": "Backwards caused quarterly without week it hungry thing someone him regularly. Whomever this revolt hence from his timing as quantity us these yours.", + "categories": ["clothing", "tools and hardware"], + "price": 7.61, + "features": ["ultra-lightweight"], + "color": "navy", + "material": "brass", + "upc": "012780949980" + }`, + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return product(r), nil + }, + }) + + AddFuncLookup("productname", Info{ + Display: "Product Name", + Category: "product", + Description: "Random product name", + Example: "olive copper monitor", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productName(r), nil + }, + }) + + AddFuncLookup("productdescription", Info{ + Display: "Product Description", + Category: "product", + Description: "Random product description", + Example: "Backwards caused quarterly without week it hungry thing someone him regularly. Whomever this revolt hence from his timing as quantity us these yours.", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productDescription(r), nil + }, + }) + + AddFuncLookup("productcategory", Info{ + Display: "Product Category", + Category: "product", + Description: "Random product category", + Example: "clothing", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productCategory(r), nil + }, + }) + + AddFuncLookup("productfeature", Info{ + Display: "Product Feature", + Category: "product", + Description: "Random product feature", + Example: "ultra-lightweight", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productFeature(r), nil + }, + }) + + AddFuncLookup("productmaterial", Info{ + Display: "Product Material", + Category: "product", + Description: "Random product material", + Example: "brass", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productMaterial(r), nil + }, + }) + + AddFuncLookup("productupc", Info{ + Display: "Product UPC", + Category: "product", + Description: "Random product UPC", + Example: "012780949980", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productUPC(r), nil + }, + }) +} diff --git a/product_test.go b/product_test.go new file mode 100644 index 00000000..16f2d355 --- /dev/null +++ b/product_test.go @@ -0,0 +1,231 @@ +package gofakeit + +import ( + "fmt" + "testing" +) + +func ExampleProduct() { + Seed(11) + product := Product() + fmt.Println(product.Name) + fmt.Println(product.Description) + fmt.Println(product.Categories) + fmt.Println(product.Price) + fmt.Println(product.Features) + fmt.Println(product.Color) + fmt.Println(product.Material) + fmt.Println(product.UPC) + + // Output: olive copper monitor + // Backwards caused quarterly without week it hungry thing someone him regularly. Whomever this revolt hence from his timing as quantity us these yours. + // [clothing tools and hardware] + // 7.61 + // [ultra-lightweight] + // navy + // brass + // 012780949980 +} + +func ExampleFaker_Product() { + f := New(11) + product := f.Product() + fmt.Println(product.Name) + fmt.Println(product.Description) + fmt.Println(product.Categories) + fmt.Println(product.Price) + fmt.Println(product.Features) + fmt.Println(product.Color) + fmt.Println(product.Material) + fmt.Println(product.UPC) + + // Output: olive copper monitor + // Backwards caused quarterly without week it hungry thing someone him regularly. Whomever this revolt hence from his timing as quantity us these yours. + // [clothing tools and hardware] + // 7.61 + // [ultra-lightweight] + // navy + // brass + // 012780949980 +} + +func TestProduct(t *testing.T) { + for i := 0; i < 1000; i++ { + product := Product() + if product.Name == "" { + t.Error("Name is empty") + } + + if product.Description == "" { + t.Error("Description is empty") + } + + if len(product.Categories) == 0 { + t.Error("Categories is empty") + } + + if product.Price == 0 { + t.Error("Price is empty") + } + + if len(product.Features) == 0 { + t.Error("Features is empty") + } + + if product.Color == "" { + t.Error("Color is empty") + } + + if product.Material == "" { + t.Error("Material is empty") + } + + if product.UPC == "" { + t.Error("UPC is empty") + } + } +} + +func BenchmarkProduct(b *testing.B) { + b.Run("package", func(b *testing.B) { + for i := 0; i < b.N; i++ { + Product() + } + }) + + b.Run("Faker math", func(b *testing.B) { + f := New(0) + + for i := 0; i < b.N; i++ { + f.Product() + } + }) + + b.Run("Faker crypto", func(b *testing.B) { + f := NewCrypto() + + for i := 0; i < b.N; i++ { + f.Product() + } + }) +} + +func ExampleProductName() { + Seed(11) + fmt.Println(ProductName()) + + // Output: appliance pulse leather +} + +func ExampleFaker_ProductName() { + f := New(11) + fmt.Println(f.ProductName()) + + // Output: appliance pulse leather +} + +func BenchmarkProductName(b *testing.B) { + for i := 0; i < b.N; i++ { + ProductName() + } +} + +func ExampleProductDescription() { + Seed(11) + fmt.Println(ProductDescription()) + + // Output: Generally half where everything niche backwards caused quarterly without week it hungry thing someone him. Today whomever this revolt hence from his timing as quantity us these yours. +} + +func ExampleFaker_ProductDescription() { + f := New(11) + fmt.Println(f.ProductDescription()) + + // Output: Generally half where everything niche backwards caused quarterly without week it hungry thing someone him. Today whomever this revolt hence from his timing as quantity us these yours. +} + +func BenchmarkProductDescription(b *testing.B) { + for i := 0; i < b.N; i++ { + ProductDescription() + } +} + +func ExampleProductCategory() { + Seed(11) + fmt.Println(ProductCategory()) + + // Output: pet supplies +} + +func ExampleFaker_ProductCategory() { + f := New(11) + fmt.Println(f.ProductCategory()) + + // Output: pet supplies +} + +func BenchmarkProductCategory(b *testing.B) { + for i := 0; i < b.N; i++ { + ProductCategory() + } +} + +func ExampleProductFeature() { + Seed(11) + fmt.Println(ProductFeature()) + + // Output: wireless +} + +func ExampleFaker_ProductFeature() { + f := New(11) + fmt.Println(f.ProductFeature()) + + // Output: wireless +} + +func BenchmarkProductFeature(b *testing.B) { + for i := 0; i < b.N; i++ { + ProductFeature() + } +} + +func ExampleProductMaterial() { + Seed(11) + fmt.Println(ProductMaterial()) + + // Output: silicon +} + +func ExampleFaker_ProductMaterial() { + f := New(11) + fmt.Println(f.ProductMaterial()) + + // Output: silicon +} + +func BenchmarkProductMaterial(b *testing.B) { + for i := 0; i < b.N; i++ { + ProductMaterial() + } +} + +func ExampleProductUPC() { + Seed(11) + fmt.Println(ProductUPC()) + + // Output: 056990598130 +} + +func ExampleFaker_ProductUPC() { + f := New(11) + fmt.Println(f.ProductUPC()) + + // Output: 056990598130 +} + +func BenchmarkProductUPC(b *testing.B) { + for i := 0; i < b.N; i++ { + ProductUPC() + } +} From 50705d5352b67eae7eb89f4f9cc4df35cd7a9891 Mon Sep 17 00:00:00 2001 From: brianvoe Date: Tue, 5 Dec 2023 17:00:12 -0600 Subject: [PATCH 9/9] readme - minor text update --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3f2c6b93..5fd32059 100644 --- a/README.md +++ b/README.md @@ -353,7 +353,7 @@ All functions also exist as methods on the Faker struct ### File -Passing `nil` to `CSV`, `JSON` or `XML` will auto generate data using a random set of generators. +Passing `nil` to `CSV`, `JSON` or `XML` will auto generate data using default values. ```go CSV(co *CSVOptions) ([]byte, error) @@ -365,7 +365,7 @@ FileMimeType() string ### Template -Passing `nil` will auto generate data using a random set of generators. +Passing `nil` will auto generate data using default values. ```go Template(co *TemplateOptions) (string, error) @@ -383,7 +383,6 @@ ProductDescription() string ProductCategory() string ProductFeature() string ProductMaterial() string - ``` ### Person